Skip to content

Conversation

@ding-young
Copy link
Contributor

@ding-young ding-young commented Nov 17, 2024

fixes #5738

Description

Above issue reports panic when formatting complex enum with generic parameters.
This is because rustfmt simply calls unwrap() on Rewrite (RewriteResult in future), the return value from format_generics.
It is better not to panic on this sort of rewrite failure.
Therefore, this pr restores original snippet when we fail to format generics in enum instead of calling unwrap().

  • This pr returns None early and then leave entire enum unformatted instead of calling unwrap().
  • visit_enum is refactored with format_enum that returns Rewrite. Later pr will replace this rewrite with RewriteResult

TODO

  • Revisit test case
  • Any other solutions ? Calling existing functions provided in visitor.rs?
  • check whether version gate is required (originally it would've panic, so I'm not sure if this is a formatting change)
  • check other related issues like Crash during rustfmt #6378
@ytmimi
Copy link
Contributor

ytmimi commented Nov 21, 2024

@ding-young thanks for picking this one up! I wonder if now would be a good time to refactor visit_enum, and introduce a format_enum function, which we can return a RewriteResult from, similar to how visit_static and visit_struct are implemented. Then if we fail to format the generics we can just return early with an error and leave the enum unformatted.

Let me know what you think?

@ytmimi
Copy link
Contributor

ytmimi commented Nov 21, 2024

Can we also add this smaller reproducible case from the original issue:

enum Node where P::<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S>>>>>>>>>>>>>>>>>>>>>>>>: { Cons, }
@ytmimi
Copy link
Contributor

ytmimi commented Nov 21, 2024

@ding-young there were also some linked issues like #6137, #6318, #6378. Would be good to check these issues out as well. #6378 doesn't seem to have a minimal test case so feel free to ignore that one.

@ding-young
Copy link
Contributor Author

Thank you for listing all the related issues! I included only the cases that originally lead to a rustfmt crash.

@ding-young
Copy link
Contributor Author

About refactoring visit_enum, I think introducing format_enum would make it easier to propagate errors later, as we wouldn't need to visit all the push_str and push_rewrite calls scattered throughout. I personally feel it may be better for users to have their enum variants formatted even if generics aren’t, and vice versa, while listing all rewrite errors if possible. Anyway, I think we can leave that for later consideration.

I still need to take a closer look to ensure the original behavior is preserved, so I’ll leave it as a draft, but it would be great if you could briefly check whether I’m refactoring in the right direction.

@ding-young ding-young marked this pull request as draft November 29, 2024 15:25
@ytmimi
Copy link
Contributor

ytmimi commented Nov 29, 2024

@ding-young thanks for looking into this refactor. I won't have time to review this PR this weekend, but I'll try to set aside some time for a review next week.

@TheLostLambda
Copy link

TheLostLambda commented Sep 30, 2025

Is this PR still the primary PR for fixing this bug? Or #6630? It would seem I'm another person who has hit the same issue! This PR fixes Rustfmt for me, but without it I can't format the project! Let me know if there is anything I can do to help move things forward!

TheLostLambda added a commit to TheLostLambda/mzdata that referenced this pull request Sep 30, 2025
I was originally perplexed as to why the crate wasn't already formatted, but quickly found out why... Though the PR seems to have languished for some time, I've run a patched version of rustfmt that completes without crashing: rust-lang/rustfmt#6396
mobiusklein pushed a commit to mobiusklein/mzdata that referenced this pull request Oct 1, 2025
#31) * style: run (patched) rustfmt I was originally perplexed as to why the crate wasn't already formatted, but quickly found out why... Though the PR seems to have languished for some time, I've run a patched version of rustfmt that completes without crashing: rust-lang/rustfmt#6396 * style: fix `mismatched_lifetime_syntaxes` lint * style: remove unnecessary macro imports This is a strange case — I had to look this up myself! Because you have a `#[macro_use]` above the `params` module in `lib.rs`, all of the macros in `params.rs` are automatically made available crate-wide. This import of the macro in `scan_properties.rs` is therefore redundant! The same logic applies to `impl_param_described`. https://lukaswirth.dev/tlborm/decl-macros/minutiae/scoping.html * style: fix clippy `derivable_impls` For `enum`s, you can add a tag and `#[derive(Default)]` instead of manually implementing the same code: https://doc.rust-lang.org/std/default/trait.Default.html#enums * style: fix clippy `single_match` * style: fix clippy `redundant_closure` * style: clippy fix `unnecessary_unwrap` * style: clippy fix `manual_is_multiple_of` NOTE: This method was added in a recent version of Rust (1.87.0), so changing to this code means that our minimum supported Rust version would become that! If you'd rather keep compatibility with older-than-stable versions of Rust, we should leave this unchanged! * chore(edition): run `cargo update` * style(edition): run `cargo --fix edition` Performs some automatic migration to the 2024 edition of Rust. Will be followed by a cleanup commit. * style(edition): bump to Rust 2024 * style(edition): reformat using (patched) rustfmt This is now a different, newer PR that supports the 2024 edition: rust-lang/rustfmt#6630 * style(edition): `expr_2021` -> `expr` in macros The 2024 edition changed `expr`s to accept `const` and `_` expressions, but because no macros in `mzdata` included any `const` or `_` keywords in their syntax, no change needs to be made. * style(edition): `match` back to `if let` None of the migrated code seemed to depend on any exact `Drop` timing, so the overly-cautious `if let` -> `match` migration was unnecessary. * style(edition): change `gen` to `this_generation` In the 2024 edition, `gen` became a reserved Rust keyword. Using `r#gen` is still possible, but probably not best practice, so I've renamed the old `gen` variables. * style: fix clippy `let_and_return` * style: fix clippy `collapsible_if`
- related issues: rust-lang#5738, rust-lang#6137, rust-lang#6318, rust-lang#6378 - instead of calling unwrap(), restore original snippet when we fail to format generics in enum - we need to propagate this rewrite failure later
- introduce format_enum that returns Rewrite - early return when it fails to format the generics in enum
@ding-young ding-young marked this pull request as ready for review October 5, 2025 14:49
@ding-young
Copy link
Contributor Author

@avrabe Hi! I've added your test case on #6630. Haven't run it on your repository, though. Would you take a look?

@TheLostLambda I lost some contexts on my pr, but maybe this pr is the primary fix, I guess. To push this change pr forward, we’ll need to find someone who has permission to merge it. I guess the core maintainers have been busy lately.

@ding-young
Copy link
Contributor Author

Would you mind reviewing this? @camsteffen @jieyouxu

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment