Handle map fields distinctly from repeated messages#15
Merged
Conversation
protoc lowers map<K, V> to a repeated message of synthetic entry types, which made map fields indistinguishable from repeated message fields and surfaced the synthetic entries as real nested messages. FieldDescriptor now detects maps: #map? plus #key/#value (the entry's key/value fields as FieldDescriptors). Map fields are excluded from #repeated?, #message?, and #scalar?, and #type_descriptor returns nil for them, so exactly one shape predicate is true. The entry is resolved from the containing message's raw nested_type rather than the context. MessageDescriptor#messages now omits synthetic map-entry types. Add scalar-, message-valued, and repeated-scalar map cases to the blog fixtures (and regenerate) to cover the distinction.
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
protoclowersmap<K, V>to a repeated message of synthetic entry types. With the field API added in #14 that made map fields indistinguishable from repeated message fields, and surfaced the synthetic entry types as if they were real nested messages:field.repeated?→true,field.message?→true, andfield.type_descriptorresolved to the synthetic<Field>Entrymessagemessage.messagesincluded the synthetic entry typesA generator walking fields/messages would emit a bogus repeated-message field and a phantom entry class. This closes that gap.
Changes
FieldDescriptor#map?— detects the map representation#key/#value— the entry's key (field 1) and value (field 2), asFieldDescriptors (sofield.value.message?,field.value.type_descriptor, etc. work)#repeated?,#message?, and#scalar?, and#type_descriptorreturnsnilfor them — so for any field exactly one shape predicate is true andif map? / elsif repeated? / else singularis cleanMessageDescriptor#messages— omits syntheticmap_entrytypes.Design note
Map detection resolves the entry from the containing message's raw
nested_typerather than viaContext. This is deliberate:Contextbuilds its type index by walking#messages, and since synthetic entries are now filtered out of#messages, a context lookup of the entry would miss. Resolving from the rawnested_typekeeps the two decoupled.Testing
Comment), repeated-scalar-is-not-a-map, and synthetic-entries-excluded-from-#messages.CommentDigestmessage added to the blog fixtures (and regenerated viabin/fixtures).bin/rake(test + rubocop): 73 runs, 191 assertions, 0 failures, rubocop clean.