Skip to content

Commit 587863b

Browse files
committed
fix: prevent panic when formatting complex generics
Handle cases where rewrite_generics fails due to long generic constraints by implementing a fallback to infinite width and preserving original formatting when necessary.
1 parent 0332da0 commit 587863b

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

src/items.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3325,7 +3325,20 @@ fn format_generics(
33253325
used_width: usize,
33263326
) -> Option<String> {
33273327
let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
3328-
let mut result = rewrite_generics(context, "", generics, shape).ok()?;
3328+
let mut result = match rewrite_generics(context, "", generics, shape) {
3329+
Ok(r) => r,
3330+
Err(_) => {
3331+
// First attempt failed, try with infinite width for complex generics
3332+
let wide_shape = shape.infinite_width();
3333+
match rewrite_generics(context, "", generics, wide_shape) {
3334+
Ok(r) => r,
3335+
Err(_) => {
3336+
// If even that fails, preserve original formatting from source
3337+
context.snippet(generics.span).to_string()
3338+
}
3339+
}
3340+
}
3341+
};
33293342

33303343
// If the generics are not parameterized then generics.span.hi() == 0,
33313344
// so we use span.lo(), which is the position after `struct Foo`.

tests/source/issue-6571.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Regression test for panic when formatting very long generic constraints
2+
// This used to cause rustfmt to panic at src/items.rs:556 with "Option::unwrap() on a None value"
3+
pub enum TestEnum<
4+
T: std::collections::HashMap<String, Vec<Box<dyn std::fmt::Debug + Send + Sync + 'static>>> + Clone + Default + PartialEq + Eq + std::fmt::Debug + serde::Serialize + serde::Deserialize<'static> + Send + Sync + 'static = std::collections::HashMap<String, Vec<Box<dyn std::fmt::Debug + Send + Sync + 'static>>>,
5+
> {
6+
Variant1(T),
7+
Variant2 { field: T },
8+
}
9+
10+
// More realistic example from real codebase
11+
pub enum ElementInit<
12+
P: wrt_foundation::MemoryProvider + Clone + Default + PartialEq + Eq = wrt_foundation::NoStdProvider<1024>,
13+
> {
14+
FuncIndices(crate::WasmVec<u32, P>),
15+
Expressions(crate::WasmVec<crate::WasmVec<u8, P>, P>),
16+
}

tests/target/issue-6571.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Regression test for panic when formatting very long generic constraints
2+
// This used to cause rustfmt to panic at src/items.rs:556 with "Option::unwrap() on a None value"
3+
pub enum TestEnum<
4+
T: std::collections::HashMap<String, Vec<Box<dyn std::fmt::Debug + Send + Sync + 'static>>> + Clone + Default + PartialEq + Eq + std::fmt::Debug + serde::Serialize + serde::Deserialize<'static> + Send + Sync + 'static = std::collections::HashMap<String, Vec<Box<dyn std::fmt::Debug + Send + Sync + 'static>>>,
5+
> {
6+
Variant1(T),
7+
Variant2 { field: T },
8+
}
9+
10+
// More realistic example from real codebase
11+
pub enum ElementInit<
12+
P: wrt_foundation::MemoryProvider + Clone + Default + PartialEq + Eq = wrt_foundation::NoStdProvider<1024>,
13+
> {
14+
FuncIndices(crate::WasmVec<u32, P>),
15+
Expressions(crate::WasmVec<crate::WasmVec<u8, P>, P>),
16+
}

0 commit comments

Comments
 (0)