Skip to content

fix: resolve oneof enum name collisions with nested types#34

Open
th0114nd wants to merge 2 commits intoanthropics:mainfrom
th0114nd:fix/nested-type-oneof-conflict
Open

fix: resolve oneof enum name collisions with nested types#34
th0114nd wants to merge 2 commits intoanthropics:mainfrom
th0114nd:fix/nested-type-oneof-conflict

Conversation

@th0114nd
Copy link
Copy Markdown

@th0114nd th0114nd commented Apr 5, 2026

Summary

Fixes #31.

When a protobuf message has a nested type (message or enum) whose PascalCase name collides with a oneof enum's PascalCase name, the codegen now suffixes the oneof enum with Oneof instead of returning a hard NestedTypeOneofConflict error.

  • oneof region_codes + message RegionCodes → generates RegionCodesOneof enum
  • oneof my_field + message MyField → generates MyFieldOneof enum
  • Non-colliding names are unchanged
  • If the suffixed name also collides with a nested type (pathological case), an OneofSuffixConflict error is returned

The suffix is applied consistently across all code paths: struct field types, enum definitions, view enums (MyFieldOneofView), binary encode/decode, text format, and JSON serde.

Changes

  • oneof.rs: Added reserved_names_for_msg() helper and modified oneof_enum_ident() to accept a reserved name set and suffix with Oneof on collision
  • message.rs: Builds reserved set, threads through oneof_enum_ident call sites
  • impl_message.rs, impl_text.rs, view.rs: Thread msg parameter to compute reserved names at each oneof_enum_ident call site
  • lib.rs: Removed check_nested_type_oneof_conflicts() upfront validation and NestedTypeOneofConflict error variant; added OneofSuffixConflict for pathological double-collision case
  • tests/naming.rs: Converted error-asserting test to success-asserting with Oneof suffix check; added tests for nested enum collision, view suffix propagation, and double-collision error

Test plan

  • Existing test_nested_type_oneof_conflict_resolved_with_suffix — nested message + oneof collision generates MyFieldOneof
  • New test_nested_enum_oneof_conflict_resolved_with_suffix — nested enum + oneof collision (gh#31 example) generates RegionCodesOneof
  • New test_nested_type_oneof_conflict_view_uses_suffix — view enum uses MyFieldOneofView
  • New test_oneof_suffix_double_collision_errors — pathological case errors cleanly
  • Existing non-collision tests still pass
  • Full workspace cargo test passes (233 tests)
  • cargo clippy --workspace -- -D warnings clean
  • No WKT regeneration needed (no collisions in well-known types)

Made with Cursor

)

When a oneof's PascalCase name collides with a nested message or enum
name in the same module, suffix the oneof enum with "Oneof" instead of
returning a hard NestedTypeOneofConflict error. This unblocks protos
like riderperks PerkRestrictions (message RegionCodes + oneof
region_codes).

The suffix is applied consistently across all code paths: struct fields,
enum definitions, view enums, binary encode/decode, text format, and
JSON serde. If the suffixed name also collides (pathological case), an
OneofSuffixConflict error is returned.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Made-with: Cursor
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 5, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@th0114nd
Copy link
Copy Markdown
Author

th0114nd commented Apr 5, 2026

I have read the CLA Document and I hereby sign the CLA

When a nested type triggers the `Oneof` suffix for one oneof enum
(e.g., `my_field` → `MyFieldOneof`), a second oneof named
`my_field_oneof` would also produce `MyFieldOneof`, creating duplicate
type names.

Introduce `resolve_oneof_idents` which processes oneofs sequentially,
growing the reserved set after each allocation. All call sites now
look up pre-computed idents instead of independently calling
`oneof_enum_ident`, ensuring consistency across struct fields, binary
encode/decode, text format, JSON serde, and view generation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Made-with: Cursor
@th0114nd
Copy link
Copy Markdown
Author

th0114nd commented Apr 5, 2026

Added a follow-up commit addressing a code review finding: sequential oneof ident allocation to prevent sibling oneofs from claiming the same suffixed name.

Example: nested message MyField, oneof my_fieldMyFieldOneof, second oneof my_field_oneof → would also produce MyFieldOneof. The fix introduces resolve_oneof_idents() which processes oneofs in declaration order, growing the reserved set after each allocation. All call sites now look up pre-computed idents from a HashMap<usize, Ident> instead of independently calling oneof_enum_ident.

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.

NestedTypeOneofConflict: codegen fails when nested message and oneof share PascalCase name

1 participant