Skip to content

Write non-numeric compact ranges in the same struct form as without compact_ranges - #629

Merged
juntyr merged 2 commits into
ron-rs:masterfrom
ybai08:fix/compact-range-fallback-struct-form
Oct 21, 2026
Merged

juntyr merged 2 commits into
ron-rs:masterfrom
ybai08:fix/compact-range-fallback-struct-form

Conversation

@ybai08

@ybai08 ybai08 commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

With compact_ranges(true), a range whose bounds are not numbers falls back to the struct form, but the fallback in SerializeStruct::serialize_field always wrote a bare ( itself. It skipped two things serialize_struct does:

  • the struct name when struct_names or the explicit_struct_names extension is on, and
  • leaving out the struct's own parentheses when the range is the content of a newtype variant under unwrap_variant_newtypes.

Two of those outputs can't be read back:

let r = String::from("a")..String::from("z");
// PrettyConfig::new().compact_ranges(true).extensions(Extensions::EXPLICIT_STRUCT_NAMES)
// master: #![enable(explicit_struct_names)](start:"a",end:"z")  -> ExpectedStructName("Range")

enum E { B(Range<String>) }
// PrettyConfig::new().compact_ranges(true).extensions(Extensions::UNWRAP_VARIANT_NEWTYPES)
// master: #![enable(unwrap_variant_newtypes)]B((start:"a",end:"z"))  -> ExpectedIdentifier

With struct_names(true) alone the name is dropped ((start:"a",end:"z") instead of Range(start:"a",end:"z")), which still parses.

RangeCompound now keeps the struct name and whether it was entered as an unwrapped newtype variant, and the fallback writes the opening the way serialize_struct would. Numeric ranges are unchanged (Numbers(0..5) inside an unwrapped variant already round-trips).

test_non_numeric_range_falls_back_to_struct_form in tests/601_support_for_number_ranges.rs checks the struct_names, explicit_struct_names and unwrap_variant_newtypes outputs and reads them back. It fails on master. A local differential check (not part of the PR) over 40 configurations (5 extension sets × struct_names × compact_structs × pretty/compact whitespace) on a struct holding Range<String>, RangeFrom<char> and newtype variants found the output with compact_ranges(true) identical to the output with compact_ranges(false), and all of them read back. cargo test, cargo test --all-features, cargo test --features integer128, cargo test --features indexmap and cargo fmt --all -- --check pass. cargo hack and the 1.64 MSRV toolchain were not run.

  • I've included my change in CHANGELOG.md

…ompact_ranges

With compact_ranges enabled, a range whose bounds are not numbers falls back
to the struct form, but that fallback always wrote a bare '(' itself. It
skipped the struct name (struct_names / explicit_struct_names) and wrote its
own parentheses inside an unwrapped newtype variant, so with
explicit_struct_names or unwrap_variant_newtypes the output could not be
deserialized again.
@ybai08
ybai08 force-pushed the fix/compact-range-fallback-struct-form branch from e258b5e to 1ba6921 Compare October 18, 2026 19:14
@juntyr

juntyr commented Oct 21, 2026

Copy link
Copy Markdown
Member

Thanks @ybai08!

@juntyr
juntyr merged commit 86bc19a into ron-rs:master Oct 21, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants