Skip to content

descriptor: reject the feature settings protoc rejects in editions files - #800

Open
veljjanoski wants to merge 2 commits into
anthropics:mainfrom
veljjanoski:descriptor-editions-feature-rules
Open

veljjanoski wants to merge 2 commits into
anthropics:mainfrom
veljjanoski:descriptor-editions-feature-rules

Conversation

@veljjanoski

Copy link
Copy Markdown
Contributor

Part of #633 (all of it except the proto2/proto3 features rule; see below).

DescriptorPool linked editions files that protoc 33.5 rejects in ValidateFieldFeatures and ValidateFileFeatures (descriptor.cc). Each case is now a new PoolError variant that names the field or file:

Input in an editions file protoc message New variant
a TYPE_GROUP field or extension Group types are not allowed under editions. GroupFieldInEditions
the packed option, either value Field option packed is not allowed under editions. PackedOptionInEditions
features.field_presence on a oneof member, a repeated or map field, or an extension; IMPLICIT on a message field Oneof fields / Repeated fields / Extensions can't specify field presence; Message fields can't specify implicit presence. InvalidFieldPresence
features.utf8_validation on a field that is not a string field or a map with a string key or value Only string fields can specify utf8 validation. InvalidUtf8Validation
features.message_encoding on a map field or a non-message field Only message fields can specify message encoding. InvalidMessageEncoding
file-level features.field_presence = LEGACY_REQUIRED Required presence can't be specified by default. LegacyRequiredFileDefault

The four protoc presence messages share one variant, as the two repeated_field_encoding messages already share InvalidRepeatedFieldEncoding. An extension set to LEGACY_REQUIRED still reports RequiredExtension.

Details that follow protoc:

  • The field rules count only a feature the field sets itself, like the existing repeated_field_encoding check, so a file default passes over the fields it does not fit. They skip the key and value fields of a map entry: protoc copies the map field's features onto them, so map<string, int32> m = 1 [features.utf8_validation = NONE] gives the int32 value field that feature too.
  • The rules apply when the file's syntax is editions and its edition is 2023 or later. protoc does not apply them to an earlier edition: a hand-built file with syntax editions and EDITION_PROTO2 is accepted with a packed option and a group. A new private is_editions_file sets LinkScope::editions; an edition this crate does not define counts as a later one. The pool's older rules (the required label, the proto3 rules) still go by the syntax string; I left them as they are.
  • PackedOptionInEditions is checked before InvalidPackedOption, so packed = true on an editions string field reports the editions rule.

I checked every case against protoc 33.5 with .proto files, and the edition gate with a hand-built descriptor set passed through protoc --descriptor_set_in.

Left out: protoc also rejects any features in a proto2 or proto3 file ("Features are only valid under editions."). The pool can't take that rule as it stands: buffa-codegen's open_enums_in and override_feature_in write features.enum_type = OPEN into proto2 enum and field descriptors, and with generate_reflection the generated descriptor_pool() loads them (for example buffa-test's open_enums.proto configs), so it would start to panic. That needs a decision on how the overrides should reach the embedded pool, so I left it for you. protoc's ValidateFileFeatures also rejects the java_string_check_utf8 file option in editions files; #633 does not list it, so it is not in this PR either.

Tests: new buffa-descriptor/tests/pool_editions_features.rs, with rejected and accepted cases for each rule. The accepted ones are the neighbours protoc accepts: a DELIMITED message field, presence on a singular field, utf8_validation on string fields and string maps, message_encoding on singular and repeated message fields, EXPLICIT/IMPLICIT file defaults, file defaults for all three features over every kind of field, and files with syntax editions and EDITION_PROTO2 or EDITION_PROTO3. Group fields cover extensions, edition 2024 and an undefined edition number, and one test checks that a rejected file leaves the pool unchanged. Each new condition was mutation-checked: disabling it fails a test.

Run locally on Windows (x86_64-pc-windows-gnu, toolchain 1.95.0, protoc 33.5):

  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets -- -D warnings, and cargo clippy -p buffa-descriptor --all-targets --all-features -- -D warnings
  • cargo test --workspace --all-features: all pass except two buffa-types tests that fail on Windows only, because SystemTime there has 100 ns resolution
  • task doc (rustdoc -D warnings)
  • the host buffa-descriptor commands of task check-nostd
  • task conformance: all eight runs pass with 0 unexpected failures, the reflect run included (it loads the protoc-built conformance protos, editions ones too, into a DescriptorPool)

AI-usage disclosure: Claude (Anthropic) was used as assistant.

@github-actions

Copy link
Copy Markdown

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

This branch has not been deployed

No deployments
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.

1 participant