Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect formatting of deeply nested block #4523

Closed
camelid opened this issue Nov 13, 2020 · 5 comments
Closed

Incorrect formatting of deeply nested block #4523

camelid opened this issue Nov 13, 2020 · 5 comments
Labels
bug Panic, non-idempotency, invalid code, etc. duplicate

Comments

@camelid
Copy link
Member

camelid commented Nov 13, 2020

Describe the bug

The inner loop and the match within are indented incorrectly.

To Reproduce

*Note: I know this code looks really bogus, but it's actually extracted from something I'm working on. I added the many layers of modules so that I could reproduce this without sharing all the code.

Playground

mod foo {
    mod bar {
        mod baz {
            mod qux {
                fn function() {
                    match self.advance() {
                        Some(_) => match self.advance() {
                            Some('\'') => self.make_token(TokenType::Char),
                            Some(_) => loop {
                                match self.advance() {
                                Some('\'') => break self.error_token(
                                    "character literals must contain exactly one Unicode character"
                                        .to_owned(),
                                ),
                                None => {
                                    break self
                                        .error_token("unterminated character literal".to_owned())
                                }
                            }
                            },
                            None => self.error_token("unterminated character literal".to_owned()),
                        },
                    }
                }
            }
        }
    }
}

Expected behavior

I guess rustfmt is having trouble because it can't make the lines fit within 100 characters, but I would rather it indent it like this:

mod foo {
    mod bar {
        mod baz {
            mod qux {
                fn function() {
                    match self.advance() {
                        Some(_) => match self.advance() {
                            Some('\'') => self.make_token(TokenType::Char),
                            Some(_) => loop {
                                match self.advance() {
                                    Some('\'') => break self.error_token(
                                        "character literals must contain exactly one Unicode character"
                                            .to_owned(),
                                    ),
                                    None => {
                                        break self
                                            .error_token("unterminated character literal".to_owned())
                                    }
                                }
                            },
                            None => self.error_token("unterminated character literal".to_owned()),
                        },
                    }
                }
            }
        }
    }
}

Meta

  • rustfmt version: rustfmt 1.4.20-stable (48f6c32 2020-08-09)
  • From where did you install rustfmt?: rustup and on the playground
  • How do you run rustfmt: VS Code and on the playground
@camelid camelid added the bug Panic, non-idempotency, invalid code, etc. label Nov 13, 2020
@camelid
Copy link
Member Author

camelid commented Nov 13, 2020

Note: for some reason it looks like this in my original code:

                    match self.advance() {
                        Some('\'') => self.make_token(TokenType::Char),
                        Some(_) => {
                            loop {
                                match self.advance() {
                                Some('\'') => break self.error_token("character literals must contain exactly one Unicode character".to_owned()),
                                None => break self.error_token("unterminated character literal".to_owned())
                            }
                            }
                        }
                        None => self.error_token("unterminated character literal".to_owned()),
                    }

Not sure why that's not happening in the MCVE 🤷

@calebcartwright
Copy link
Member

Closing as duplicate of #3863

The problem is the string arg to self.error_token which would exceed the max_width limit no matter what rustfmt does. rustfmt won't explicitly re-format in a way that exceeds the width limit, so the formatting fails back up a few nodes and the original snippet is inserted instead.

Tactical approaches you can consider leveraging to address this are to turn on format_strings to give rustfmt permission to try to format that string arg to attempt to stay within the max width bounds, or break the string up into fit-able chunks yourself, or move the string to a local and use that local as the arg instead of the lit

@camelid
Copy link
Member Author

camelid commented Nov 13, 2020

Yeah, I ended up fixing it by moving it into a function, which makes the code easier to understand anyway. It was just frustrating that rustfmt would format it poorly and there was no way to stop it.

@calebcartwright
Copy link
Member

It was just frustrating that rustfmt would format it poorly and there was no way to stop it.

Could you elaborate on this a bit? With the chain/max_width issue, rustfmt isn't doing any formatting, but is simply leaving your original formatting in place. This would have then required manual formatting, but rustfmt shouldn't have been fighting your manual formatting (providing the same line length issue still existed)

@camelid
Copy link
Member Author

camelid commented Nov 13, 2020

Hmm, it looks like it is letting me do it after all. Not sure why I thought it wasn't. Sorry about that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Panic, non-idempotency, invalid code, etc. duplicate
Projects
None yet
Development

No branches or pull requests

2 participants