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.

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

Successfully merging this pull request may close these issues.

panic: Option::unwrap() on a None value
4 participants