github cue-lang/cue v0.3.0-beta.2

latest releases: v0.9.0-alpha.5, v0.9.0-alpha.4, v0.8.2...
2 years ago

This release predominantly addresses some regressions and bug fixes. There are also some additional small performance fixes.

Backwards compatibility

There are a couple of bug fixes that may lead to backwards incompatibilities.

Disjunction disambiguation and “incomplete” errors

There were some bug fixes where disjunctions were discarded as duplicates prematurely. This was already an issue since v0.3.0-alpha1. As a result, you may now get an “incomplete value” error where before you didn’t. For instance, {a: int, c?: int} | {a: int, b?: int} now will remain as two separate disjuncts, whereas previously it was assumed evaluation was done too early that the optional fields were irrelevant.

In v0.2.2 this would also not be disambiguated. There are, however, still some differences between v0.2 and v0.3. Pre-v0.3 CUE used subsumption to disambiguate disjuncts. Subsumption is inherently imprecise and allows false negatives. This would inherently make it hard to predict when values were disambiguated. As subsumption was used at no other place during evaluation, v0.3 takes a simpler approach to only check for equality, whereby optional fields are only considered equal if they originate from the same original structs.

The general idea is that one should typically not have disjunctions of structs without those having discriminator fields (i.e. the disjuncts would fail if unified with each other, for instance with a kind field with a specific value, like K8s does). If one still needs this, then one of the structs should be marked as default to disambiguate.

In other words, v0.3 may give an “incomplete error” where v0.2 did not. For instance: #Fields: _ | [string]: #Fields would normalize away with v0.2, but won’t with v0.3. The simple solution is to use _ or {...}. The v0.3.0-alpha releases had a bug that would prevent these alternatives from working properly, but that has been fixed as of beta.1.

We may still consider allowing more disambiguation at the point of making values concrete. This will need to be considered carefully, though. We may also allow some compile-time optimizations, like translating _ | X to _. We have not done so yet, as a set of rules for such translations has the danger of making disambiguation arbitrary; we would like If people have trouble migrating to v0.3.0-beta.2, we can prioritize such simplification rules for beta.3.

We intend to come up with a set of clear and predictable rules before v0.3.0 on when CUE may disambiguate disjunctions. Until that time, please ensure that disjunctions with structs are disambiguated using defaults and discriminator fields. This should generally be considered to be proper style and highly recommendable anyway. Note that any protocol buffer and all K8s structs, for instance, follow a pattern that can be disambiguated easily.

Stricter closedness as a result of a bug fix

The value #B: {#A} & {a: 1} is now interpreted as #B: #A & {a: 1}. Previously, this was interpreted as #B: {#A, a: 1}, allowing field a regardless of whether #A allows it or not. This was a leftover of the old closedness rules of pre-v0.3.0. The old rules were somewhat convoluted and based on user feedback and experience we simplified the rules and made them more intuitive for v0.3.0.

API

We have added the list.Concat and list.Repeat builtins in anticipation of removing the * and + operators for lists in CUE. These operators are quite unintuitive as it is not clear how they interact with closedness, which has raised repeated questions. They also complicate the implementation. This has been mitigated by, internally, translating list addition to list of two list comprehensions. They also complicated automated analysis, which is harder to work around. Better to get rid of them altogether.

The next steps for the transition is to let cue fix automatically rewrite list addition and multiplications in terms of their builtins. Ultimately list addition could be replaced with a query shorthand, like [a] + [b] -> [ a.*, b.* ], using a.* as the hypothetical notation for all values of a.

Performance

We have seen some considerable performance improvements for some configurations. There is still plenty of room for improvement though, both algorithmically, which can bring long-running evaluations down to below a second or two, and by reducing the constant overhead, by itself allowing a running time reduction of at least another 90% in many cases. So if there are any pressing performance issues, we would love to hear about them.

Changelog

ed7d254 ci: delete CL build branches once workflow is complete
8c41622 ci: fix dispatch workflow
ccbfbd2 ci: move to build branch model
237a4ae ci: use the latest GitHub workflow definition
f1b1804 cmd/cue/cmd/getgo: don't be clever
ff48658 doc/ref/spec.md: disallow new definitions in closed structs
172f006 doc/ref/spec.md: get rid of list operators
5691606 internal/core/adt: add test for incomplete references in lets
bef7b26 internal/core/adt: fix cycle bug
a086f74 internal/core/adt: fix disjunct dedupping regression
ae1203c internal/core/adt: fix overzealous disambiguation
826bd7b internal/core/adt: fix regression in close builtin
34a91b9 internal/core/adt: fix some regressions
663939e internal/core/adt: improve errors for validator conflicts
13b68c8 internal/core/adt: minor cleanup
355cccd internal/core/adt: precompute optional field type info
9eee235 internal/core/adt: remove special "tentative" mode
2ef72d8 internal/core/eval: fix result of closed embedding
03aab97 internal/core: re-allow new definitions in closed structs
0ffde15 pkg/internal: fix error codes for decimal and string lists
867f71f pkg/list: add builtins for list concatenation and repetition

Don't miss a new cue release

NewReleases is sending notifications on new releases.