Skip to content

Conversation

avrabe
Copy link

@avrabe avrabe commented Aug 10, 2025

Fixes #6571

Problem

rustfmt panics with Option::unwrap() on a None value when formatting enums with very long generic type constraints. This occurs when the generic constraints exceed the available width budget (~80-100 characters), causing rewrite_generics to fail and format_generics to return None, which is then unwrapped.

Solution

This PR implements a three-tier fallback strategy in format_generics:

  1. First attempt: Try formatting with normal width constraint
  2. Second attempt: If that fails, retry with infinite width using shape.infinite_width()
  3. Fallback: If even that fails, preserve the original source formatting

Changes

  • Modified format_generics function in src/items.rs to handle width budget exhaustion gracefully
  • Added regression test case issue-6571.rs to prevent future regressions

Testing

  • All existing tests pass
  • New regression test verifies the fix works for complex generic constraints
  • Tested on the original failing codebase that triggered the issue

This fix ensures rustfmt can process files with complex generic constraints without crashing, while maintaining proper formatting where possible.

Handle cases where rewrite_generics fails due to long generic constraints
by implementing a fallback to infinite width and preserving original
formatting when necessary.
@ding-young
Copy link
Contributor

ding-young commented Aug 31, 2025

Hi, I just came across your PR. Would it be alright if I try it out to see if #6396 fixes the unwrap error in that test case? (This seems orthogonal to the mentioned PR though, so just to verify whether the issue is duplicate or not)

@avrabe
Copy link
Author

avrabe commented Sep 1, 2025

@ding-young Sure, would be good to see. https://github.com/pulseengine/wrt is where my problem originate from. My patch makes this repository format again. Otherwise it actually stripped away code.

TheLostLambda added a commit to TheLostLambda/mzdata that referenced this pull request Sep 30, 2025
This is now a different, newer PR that supports the 2024 edition:
rust-lang/rustfmt#6630
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`
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.

rustfmt panic: Option::unwrap() on None value in items.rs:562
3 participants