internal/core/adt: allow any CUE value in json/yaml.Validate
By default, when calling builtin functions, an error is returned
for each argument that is:
- non-concrete (i.e. builtin(`string`))
- an unresolved disjunction (i.e. builtin("a" | "b"))
In addition, all default values are resolved, so that `builtin(1 | *2)`
will be called as `builtin(2)`, losing important data in some cases
where the disjunction could be resolved to `1`.
Some examples in which this behavior is erroneous:
- `yaml.Validate("a", "a" | "b")` (results in an "unresolved
disjunction" error)
- `yaml.Validate("a", string)` (results in a non-concrete value error)
- `yaml.Validate("a", *int | string)` (even if non-concrete values
were allowed, this would result in false because the default value
`int` would be resolved in place of the disjunction, and 'a' is
not an int)
To fix this, we delegate the responsibility to evaluate disjunctions
and resolve default values to the builtin. This way each builtin can
decide whether its arguments should be concrete, and whether
disjunctions/defaults should be resolved.
Note: these are further original comments from Noam. The corresponding
code has been hoisted to a separate CL
A new CallCtxt.Schema method is added which, as opposed to
CallCtxt.Value, does not resolve arguments to their default values /
enforce concreteness.
All stdlib function registrations, located in pkg.go files, are
auto-generated based on the public functions in the corresponding
stdlib packages. Because of this, a new `internal.pkg.Schema` type
is added, so that stdlib functions that need to use CallCtxt.Schema,
can declare a parameter astype pkg.Schema.
This fixes incorrect failures when passing non-concrete values and
unresolved disjunctions to `yaml.Validate` and `json.Validate`.
A test is added that only works when the new evaluator is enabled. This
is because the old evaluator evaluated the following CUE as incomplete:
{a: 1} & ({a!: int} | {b!: int})
Which is incorect because the required fields should "force" the
expression to evaluate to `{a: 1}`.
Note that this does not yet fix cases like:
yaml.Validate("a: 1", close({a: int}) | close({b: int}))
This will require further investigation to see why the "closedness" of
the disjuncts is seemingly lost during the evaluation, resulting in a
non-concrete unification of the yaml with the disjunction - and a false
result.
Updates #2741.
Signed-off-by: Noam Dolovich <noam.tzvi.dolovich@gmail.com>
Change-Id: Id34b5ada4704df0e43ff9ea33ad47d631af9ba74
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1194425
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
authored by