Repository: rust-lang/rustfmt (rust)

Issue:
Feature request: Customizable `SHORT_ITEM_THRESHOLD`
This is a follow up issue to #5219. I found that I cannot format 
```rust
pub const FORMAT_TEST: [u64; 5] = [
    0x0000000000000000,
    0xaaaaaaaaaaaaaaaa,
    0xbbbbbbbbbbbbbbbb,
    0xcccccccccccccccc,
    0xdddddddddddddddd,
];
```
to something like
```rust
pub const FORMAT_TEST: [u64; 5] = [
    0x0000000000000000, 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb,
    0xcccccccccccccccc, 0xdddddddddddddddd,
];
```
due to the limit set by [`SHORT_ITEM_THRESHOLD`](https://github.com/rust-lang/rustfmt/blob/0b8ffac0297a46d7d2d2f8328cbc49de7e7144f2/src/overflow.rs#L29). I tried changing this threshold to 20, and then I managed to get the array formatted as the latter style.

Therefore I would like to request the ability to customize this limit, or at least override it for integer literals specifically. Thanks!

<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":"123vivekr"}$$TRIAGEBOT_ASSIGN_DATA_END -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->

Pull request:
Add `short_item_threshold` config option
Allow custom short item threshold values via config

Closes #5225

Patch:
diff --git a/Configurations.md b/Configurations.md
index ecec97dc..a47439b9 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -2200,6 +2200,40 @@ specific version of rustfmt is used in your CI, use this option.
 - **Possible values**: any published version (e.g. `"0.3.8"`)
 - **Stable**: No (tracking issue: [#3386](https://github.com/rust-lang/rustfmt/issues/3386))
 
+## `short_array_element_width_threshold`
+
+The width threshold for an array element to be considered "short".
+
+The layout of an array is dependent on the length of each of its elements. 
+If the length of every element in an array is below this threshold (all elements are "short") then the array can be formatted in the mixed/compressed style, but if any one element has a length that exceeds this threshold then the array elements will have to be formatted vertically.
+
+- **Default value**: `10`
+- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
+- **Stable**: Yes
+
+#### `10` (default):
+```rust
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
+```
+#### `20`:
+```rust
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000, 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
+```
+See also [`max_width`](#max_width).
+
 ## `skip_children`
 
 Don't reformat out of line modules
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 5041e1e3..18e18546 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -106,6 +106,8 @@ create_config! {
     // Misc.
     remove_nested_parens: bool, true, true, "Remove nested parens";
     combine_control_expr: bool, true, false, "Combine control expressions with function calls";
+    short_array_element_width_threshold: usize, 10, true,
+        "Width threshold for an array element to be considered short";
     overflow_delimited_expr: bool, false, false,
         "Allow trailing bracket/brace delimited expressions to overflow";
     struct_field_align_threshold: usize, 0, false,
@@ -591,6 +593,7 @@ spaces_around_ranges = false
 binop_separator = "Front"
 remove_nested_parens = true
 combine_control_expr = true
+short_array_element_width_threshold = 10
 overflow_delimited_expr = false
 struct_field_align_threshold = 0
 enum_discrim_align_threshold = 0
diff --git a/src/items.rs b/src/items.rs
index 9b35d28f..92f423bb 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1273,7 +1273,13 @@ pub(crate) fn format_struct_struct(
     result.push_str(&header_str);
 
     let header_hi = struct_parts.ident.span.hi();
-    let body_lo = context.snippet_provider.span_after(span, "{");
+    let body_lo = if let Some(generics) = struct_parts.generics {
+        // Adjust the span to start at the end of the generic arguments before searching for the '{'
+        let span = span.with_lo(generics.span.hi());
+        context.snippet_provider.span_after(span, "{")
+    } else {
+        context.snippet_provider.span_after(span, "{")
+    };
 
     let generics_str = match struct_parts.generics {
         Some(g) => format_generics(
diff --git a/src/overflow.rs b/src/overflow.rs
index 3475f5c3..80aed998 100644
--- a/src/overflow.rs
+++ b/src/overflow.rs
@@ -26,8 +26,6 @@ use crate::spanned::Spanned;
 use crate::types::{can_be_overflowed_type, SegmentParam};
 use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp};
 
-const SHORT_ITEM_THRESHOLD: usize = 10;
-
 /// A list of `format!`-like macros, that take a long format string and a list of arguments to
 /// format.
 ///
@@ -572,7 +570,12 @@ impl<'a> Context<'a> {
                             if one_line {
                                 tactic = DefinitiveListTactic::SpecialMacro(num_args_before);
                             };
-                        } else if is_every_expr_simple(&self.items) && no_long_items(list_items) {
+                        } else if is_every_expr_simple(&self.items)
+                            && no_long_items(
+                                list_items,
+                                self.context.config.short_array_element_width_threshold(),
+                            )
+                        {
                             tactic = DefinitiveListTactic::Mixed;
                         }
                     }
@@ -755,9 +758,9 @@ fn shape_from_indent_style(
     }
 }
 
-fn no_long_items(list: &[ListItem]) -> bool {
+fn no_long_items(list: &[ListItem], short_array_element_width_threshold: usize) -> bool {
     list.iter()
-        .all(|item| item.inner_as_ref().len() <= SHORT_ITEM_THRESHOLD)
+        .all(|item| item.inner_as_ref().len() <= short_array_element_width_threshold)
 }
 
 /// In case special-case style is required, returns an offset from which we start horizontal layout.


Test patch:
diff --git a/tests/source/configs/short_array_element_width_threshold/10.rs b/tests/source/configs/short_array_element_width_threshold/10.rs
new file mode 100644
index 00000000..7d0d7091
--- /dev/null
+++ b/tests/source/configs/short_array_element_width_threshold/10.rs
@@ -0,0 +1,11 @@
+// rustfmt-short_array_element_width_threshold: 10
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
\ No newline at end of file
diff --git a/tests/source/configs/short_array_element_width_threshold/20.rs b/tests/source/configs/short_array_element_width_threshold/20.rs
new file mode 100644
index 00000000..8a93a51d
--- /dev/null
+++ b/tests/source/configs/short_array_element_width_threshold/20.rs
@@ -0,0 +1,11 @@
+// rustfmt-short_array_element_width_threshold: 20
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
\ No newline at end of file
diff --git a/tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs b/tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs
new file mode 100644
index 00000000..710b6fe7
--- /dev/null
+++ b/tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs
@@ -0,0 +1,12 @@
+// rustfmt-max_width: 20
+// rustfmt-short_array_element_width_threshold: 30
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
diff --git a/tests/target/configs/short_array_element_width_threshold/10.rs b/tests/target/configs/short_array_element_width_threshold/10.rs
new file mode 100644
index 00000000..78c4adba
--- /dev/null
+++ b/tests/target/configs/short_array_element_width_threshold/10.rs
@@ -0,0 +1,11 @@
+// rustfmt-short_array_element_width_threshold: 10
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
diff --git a/tests/target/configs/short_array_element_width_threshold/20.rs b/tests/target/configs/short_array_element_width_threshold/20.rs
new file mode 100644
index 00000000..60846906
--- /dev/null
+++ b/tests/target/configs/short_array_element_width_threshold/20.rs
@@ -0,0 +1,8 @@
+// rustfmt-short_array_element_width_threshold: 20
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000, 0xaaaaaaaaaaaaaaaa, 0xbbbbbbbbbbbbbbbb, 0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
diff --git a/tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs b/tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs
new file mode 100644
index 00000000..710b6fe7
--- /dev/null
+++ b/tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs
@@ -0,0 +1,12 @@
+// rustfmt-max_width: 20
+// rustfmt-short_array_element_width_threshold: 30
+
+fn main() {
+    pub const FORMAT_TEST: [u64; 5] = [
+        0x0000000000000000,
+        0xaaaaaaaaaaaaaaaa,
+        0xbbbbbbbbbbbbbbbb,
+        0xcccccccccccccccc,
+        0xdddddddddddddddd,
+    ];
+}
diff --git a/tests/target/issue_5273.rs b/tests/target/issue_5273.rs
new file mode 100644
index 00000000..3bb9048a
--- /dev/null
+++ b/tests/target/issue_5273.rs
@@ -0,0 +1,3 @@
+struct Example<const N: usize = { 1048576 }> {
+    //
+}