Skip to content

CEL spec 0.25.2 conformance#943

Open
snazy wants to merge 33 commits into
projectnessie:mainfrom
snazy:cel-0-25-2
Open

CEL spec 0.25.2 conformance#943
snazy wants to merge 33 commits into
projectnessie:mainfrom
snazy:cel-0-25-2

Conversation

@snazy

@snazy snazy commented Jul 27, 2026

Copy link
Copy Markdown
Member

This PR makes CEL-Java conformant to the CEL 0.25.2 specification.

Many of the the individual changes, left as separate commits, touch the same files.

The end result is that effectively all CEL 0.25.2 conformance are enabled and pass.

Strong-enum support is intentionally not enabled, because that's not part of the language specification and are mutually incompatible with the enum-as-int conformance sections.

snazy added 30 commits July 27, 2026 08:50
Update string-to-bool conversion to accept the CEL-Spec spellings while rejecting unsupported mixed-case values.

Compare type values by CEL type name so well-known object type values match their built-in timestamp and duration type values.

Allow null assignment to wrapper fields and leave wrapper, message, timestamp, and duration fields unset during protobuf construction.

Support backtick-quoted field names in select expressions and message field initializers, then remove the now-passing conformance skips.
Handle CEL null values at the protobuf construction boundary for repeated and map fields whose value type is timestamp, duration, or a protobuf wrapper.

Convert map message values to the actual target protobuf message type instead of always using google.protobuf.Value.

Avoid hasField() for repeated wrapper fields when reading protobuf values, since repeated fields do not support presence checks.
The map Any null-retention conformance cases now pass after the protobuf map conversion changes.

Remove the proto2 and proto3 skip entries so the JUnit conformance suite covers those cases.
Protobuf message construction could let bad field conversions escape as Java runtime exceptions, which broke disabled-check conformance cases expecting evaluation errors.

Wrap field conversion and assignment failures from newValue() as CEL Err values, add provider coverage for invalid null assignments, and enable the remaining proto2/proto3 set_null conformance cases.
Include the CEL-Spec type_deduction suite in the JUnit conformance runner to cover checker result types for already-supported language features.

Keep explicit skips for the remaining unsupported checker cases around optionals, flexible type parameter generality, wrapper promotion, and legacy nullable generic candidates.
The dynamic float protobuf range-assignment cases now pass under the JUnit conformance runner.

Remove the stale proto2 and proto3 float range skip entries while keeping the int32 and uint32 range cases skipped because they still overflow into protobuf field values instead of returning range errors.
The legacy proto2 and proto3 standalone enum out-of-range assignment cases now pass under the JUnit conformance runner.

Remove the stale skip entries for the too-large and too-negative enum assignment cases.
Int32Value and UInt32Value native conversions accepted values outside their protobuf wrapper ranges by truncating them to Java int.

Add range checks for those wrapper conversions, cover the error paths in unit tests, and enable the int32 and uint32 dynamic range conformance cases.
Unsigned CEL uint values stored in negative Java long values were treated as JSON numbers because the conversion compared the signed long directly.

Use unsigned comparison for uint-to-JSON conversion, add coverage for the uint64 max value, and enable the uint64 wrapper JSON conformance case.
Timestamp JSON conversion returned a wrapper message instead of google.protobuf.Value and omitted fractional seconds. FieldMask was also missing from the default well-known protobuf registration path, which kept its conformance case from checking.

Return proper JSON Value instances for timestamp conversion, register FieldMask in the default protobuf type metadata, add narrow JSON Value conversion for FieldMask, Timestamp, and Empty message objects, and enable the corresponding wrapper JSON conformance cases.
CEL map literals only support bool, int, uint, and string keys. Unchecked map literals with float keys were accepted at evaluation time and could resolve through numeric key equality instead of producing the expected unsupported-key-type error.

Validate literal map keys during evaluation with the supported CEL key-type set, preserve native object map wrapping behavior for Jackson-backed objects, add interpreter coverage, and enable the corresponding conformance case.
Generated protobuf message equality treats NaN fields as equal, but CEL protobuf equality treats messages with present NaN float or double fields as not equal.

Add protobuf-object equality handling that detects NaN float and double fields, including nested and repeated message fields, update interpreter coverage, and enable the matching conformance cases.
Conformance bindings can provide google.protobuf.Any object values whose payload is the expected application message. The result conversion path preserved neither existing Any values nor nested Any payload shape, producing an extra wrapper compared with the expected object value.

Preserve evaluated Any object values, unwrap nested Any payloads when converting evaluation results back to conformance values, and enable the matching dynamic Any conformance case.
CEL maps were converted to protobuf Struct values by coercing every key through CEL string conversion. That allowed invalid message construction such as assigning {1: 'one'} to a google.protobuf.Struct field, producing a Struct with key "1" instead of an eval error.

Require map keys to already be CEL strings when converting to protobuf Struct values. Add direct map conversion and protobuf message construction regression coverage, and enable the corresponding dynamic struct conformance cases.
The proto3 float assignment case for a negative-zero value now passes under the current protobuf conversion behavior. The skip list still marked it as unsupported, which kept valid conformance coverage disabled.

Remove the stale skip so the dynamic float assignment case runs with the rest of the simple conformance suite.
List literal element type deduction was order-sensitive for matching primitive and wrapper types. When a wrapper appeared before its primitive, the common type was reduced to the primitive, while the reverse order preserved the wrapper type.

Prefer the matching wrapper type as the common type for primitive/wrapper unification, add checker coverage for both element orders, and enable the wrapper promotion conformance case.
List literal type deduction selected null as the common type when nullable concrete values were joined with null. This caused message, duration, and timestamp candidates to lose their concrete element type.

Prefer the nullable concrete type when it is unified with null, add checker coverage for both element orders, and enable the corresponding legacy nullable conformance cases.
The checker only freshened overload type parameters listed explicitly on the overload declaration. Conformance declarations can also use type_param entries directly in the parameter or result types, which left raw type parameters in resolved result types and broke later overload matching.

Classify protobuf abstract types, derive overload type parameters from the full overload signature, and expose current substitutions while checking nested expressions so comprehension results keep refined accumulator types. Enable the matching type-deduction conformance cases.
Namespace resolution preferred container-qualified identifiers before lexical fold variables, so comprehension-local names could resolve to outer bindings. Parsed-only ASTs had the same issue through maybe-attribute resolution, and leading-dot absolute references could not bypass local fold variables.

Make checker lookup prefer current lexical identifiers only in nested scopes, keep absolute references marked for evaluation, and make unchecked attributes prefer current fold variables before namespaced candidates. Add regression coverage and enable the namespace shadowing conformance cases.
Proto extension descriptors were not indexed as fields, so checked expressions could not resolve extension selects and parsed-only evaluation treated extension fields as absent. Any payloads with extension fields also lost those values when decoded without an extension registry.

Index file-level and message-scoped extension descriptors, resolve them for matching containing message types, and use descriptor-backed extension registries when unpacking Any values. Add regression coverage and enable the proto2 extension has/get conformance cases.
The CEL proto extension conformance suite uses proto.hasExt/proto.getExt and references protobuf extension identifiers as expression values. Those identifiers were not available through checker/provider resolution, and the helper functions were not exposed as an explicit extension library.

Expose registered protobuf extension names as string constants, add the opt-in proto extension library functions, and run the proto2 extension conformance file through that library.
The CEL string extension conformance file covers APIs that are already implemented by StringsLib, but the harness did not include that file or enable the library for those expressions.

Add the string extension conformance file with explicit skips for unsupported quote, format, and reverse sections. Tighten multi-arity string extension dispatch so calls with too many arguments return no-such-overload instead of evaluating the expected argument prefix.
The string extension conformance file still skipped quote, format, format error, and reverse coverage. StringsLib also lacked the corresponding declarations and runtime implementations.

Add strings.quote, reverse, and CEL string formatting support for the covered clauses, including recursive list and map rendering. Fix escaped string literal unescaping for raw non-BMP Unicode code points, and remove the remaining string extension conformance skips.
The CEL-Spec type-deduction suite uses optional.none and optional.of in check-only cases. Those expressions could not type-check because the optional helper functions were not declared.

Add an opt-in optional library with compile-time declarations for the optional helper functions, and use it in the conformance harness for optional expressions. This enables optional type deduction without adding runtime optional semantics.
The strong enum sections contain a mix of unsupported typed-enum semantics and cases that already work with the current int-backed enum behavior.

Replace the broad section skips with targeted skips for the remaining typed-enum gaps, and convert conformance enum_value bindings to integer values so disabled-check conversion cases can run.
The nested protobuf message literal case now passes under the current conformance runner and evaluator.

Remove the stale skip so the parse nesting coverage runs with the rest of the CEL-Spec simple suite.
The CEL-Spec encoder extension suite covers Base64 encode and decode helpers, including decode input without padding.

Add an opt-in encoder extension library with base64.encode and base64.decode, wire it into the conformance harness for base64 expressions, and include direct core coverage for successful and invalid decode inputs.
The CEL-Spec bindings extension uses cel.bind to introduce a local variable in the result expression. CEL-Java parsed those expressions as ordinary calls, so the checker reported undeclared local variables.

Add cel.bind as a standard macro, expanding it to a single-iteration comprehension with a dynamic accumulator initializer. Add direct macro coverage and include bindings_ext.textproto in the conformance suite.
The CEL-Spec math extension suite exercises numeric helpers such as min/max, rounding, finite checks, and bitwise operations. CEL-Java did not expose those extension functions, so the suite could not be enabled.

Add an opt-in math extension library, wire it into the conformance harness for math expressions, and include direct coverage for representative numeric, rounding, and bitwise cases.
The CEL-Spec network extension suite requires net.IP and net.CIDR values with strict literal parsing, canonical formatting, receiver methods, and type-literal support. CEL-Java did not expose those extension functions or custom network types.

Add an opt-in network extension library, support custom object type values with explicit traits, wire the library into the conformance harness, and cover representative IP and CIDR behavior with direct tests.
snazy added 3 commits July 27, 2026 08:50
The CEL-Spec block suite uses test-only macros to model sequential local bindings and generated comprehension variable names. CEL-Java did not provide those macros, so the suite could not be parsed or executed in the pure Java conformance harness.

Add opt-in parser macros for the block conformance cases, keep them out of the default macro set, wire them into the conformance parser only when needed, and enable block_ext with explicit skips for the optional-dependent cases.
The updated CEL-Spec includes macros that expose both key/index and value variables during comprehension evaluation. CEL-Java only modeled one iteration variable, which prevented exists/all/existsOne and transform macros from covering list indexes and map values.

Add parser, checker, and interpreter support for the second comprehension variable, add transformList and transformMap macro expansion, preserve iter_var2 in AST pruning and exhaustive evaluation, and enable the macros2 conformance file with direct unit coverage.
@snazy
snazy requested a review from XN137 July 27, 2026 06:57
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