Repository navigation
codegen: reject a message with two fields that share a field number - #716
Merged
iainmcgin merged 3 commits intoOct 20, 2026
Merged
Conversation
A descriptor that protoc did not produce can give two fields one number. table_fields sorted them into adjacent table entries, and the consumer's crate failed to compile on the const panic in Table::new, which names neither the message nor the field. table_fields now returns Ineligible for the first such pair, naming both fields, so the message falls back to the unrolled codec; an exact-path codec_strategy_in rule for it is an error. The dense_lookup error this made unreachable stays as a backstop. Fixes anthropics#706
|
All contributors have signed the CLA ✍️ ✅ |
The fallback to the unrolled codec left code that compiles and loses
data: with two int32 fields numbered 1, {a: 5, b: 7} encodes as
[8, 5, 8, 7] and decodes as {a: 7, b: 0}, with an unreachable_patterns
warning in the generated decoder.
generate now returns CodeGenError::DuplicateFieldNumber for a message
of a generated file that has two fields with one number. The check runs
before the table plan, so a message that also cannot use the table gets
this error and not the plan's advice to select the unrolled codec. The
Ineligible reason in table_fields and its guide bullet are removed.
Two test fixtures had a duplicate number by accident and are corrected.
iainmcgin
reviewed
Oct 16, 2026
iainmcgin
left a comment
Collaborator
There was a problem hiding this comment.
[claude code] Thanks for offering the switch. The maintainer decision is the hard error: the fallback leaves unrolled code that compiles and loses data. With two int32 fields numbered 1, {a: 5, b: 7} encodes as [8, 5, 8, 7] and decodes as {a: 7, b: 0}, with an unreachable_patterns warning in the generated decoder.
Pushed one maintainer commit on top of yours (a471391):
generatereturns the newCodeGenError::DuplicateFieldNumber { message_name, first_field, second_field, number }for a message of a generated file that has two fields with one number, whichever codec is selected. It is checked before the table plan, so a message that also cannot use the table gets this error and not the plan advice to select the unrolled codec.- The
Ineligiblecheck intable_fieldsand the guide bullet are removed (adebug_assert!keeps the invariant), and thedense_lookupdoc points at the new error. - Tests: the three fallback tests become four that expect the error: every strategy, including an exact-path rule for a message that is also table-ineligible; a nested message with a oneof member; 256 duplicates; a file that is not generated. Two existing fixtures had a duplicate number by accident (
tests/naming.rs,tests/shared_corpus_context.rs) and are corrected. - The fragment is rewritten and renamed.
cargo test --workspace passes on this head (4273 passed, 0 failed). The title and description will be updated to match.
Contributor
Author
|
Thanks for taking this over the line. The hard error is the better outcome. I've updated the title and description to match a471391. |
iainmcgin
approved these changes
Oct 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #706.
A descriptor that protoc did not produce can have two fields of one message with the same number, and codegen accepted it. With
CodecStrategy::Tablethe consumer's crate failed to compile on a const panic inTable::newthat did not identify the message or the field. With the default codec the crate compiled with anunreachable_patternswarning and lost data: with twoint32fields numbered 1,{a: 5, b: 7}encodes as[8, 5, 8, 7]and decodes as{a: 7, b: 0}.generatenow returns the newCodeGenError::DuplicateFieldNumber, which reports the message, both fields and the number, for every message of a generated file, whichever codec is selected. Files that are only imported, and packages underexclude_package, are not checked.Of the issue's two outcomes this is the hard error: a fallback to the unrolled codec would have kept the data loss.
Not checked here: an extension's number against its extendee's fields (#626 covers the descriptors that codegen accepts and
DescriptorPoolrejects).dense_lookup's error for more than 255 low-numbered fields stays as a backstop thatgenerateno longer reaches, so it has no test.Two existing test fixtures had a duplicate number by accident and are corrected.