Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spec: decide whether CUE should support NaN and Infinity values #3168

Open
mvdan opened this issue May 23, 2024 · 1 comment
Open

spec: decide whether CUE should support NaN and Infinity values #3168

mvdan opened this issue May 23, 2024 · 1 comment

Comments

@mvdan
Copy link
Member

mvdan commented May 23, 2024

Right now, the CUE spec makes zero mentions of NaN "not a number" or any infinity numbers, positive or negative.

https://pkg.go.dev/cuelang.org/go/pkg/math has multiple mentions of them, but they seem to be carried over from https://pkg.go.dev/math, perhaps by mistake. At least the functions NaN, Inf, IsNaN, and IsInf were not included.

The spec does have a TODO about this:

The result of division by zero is bottom (an error).
<!-- TODO: consider making it +/- Inf -->
Integer division is implemented through the builtin functions
`quo`, `rem`, `div`, and `mod`.

This is a problem for some encodings which support these special float values, such as YAML. The YAML decoder has test cases that check that we decode .Inf as +Inf, or .NaN as NaN, but none of those are valid CUE values. I believe these test cases were carried over from go-yaml and we hadn't noticed because our YAML decoder tests didn't sanity check that the resulting CUE was valid... until now, when I started making the YAML tests do just that.

I poked around a bit more, and it turns out that the evaluator itself, or at least the pkg/math APIs, are rather inconsistent in how they deal with situations where NaN or Infinity emerge:

# Division by zero is an error, which makes some sense.
! exec cue eval posinf_divzero.cue
cmp stderr posinf_divzero.stderr

# pkg/math can return CUE values like "Infinity.0", "-Infinity", or "NaN.0", which are invalid.
exec cue eval posinf_math.cue
cmp stdout posinf_math.stdout
exec cue eval neginf_math.cue
cmp stdout neginf_math.stdout
exec cue eval nan_math.cue
cmp stdout nan_math.stdout

-- posinf_divzero.cue --
output: 1 / 0
-- posinf_divzero.stderr --
output: failed arithmetic: division by zero:
    ./posinf_divzero.cue:1:9
-- posinf_math.cue --
import "math"

output: math.Atanh(1)
-- posinf_math.stdout --
output: Infinity.0
-- neginf_math.cue --
import "math"

output: math.Log(0)
-- neginf_math.stdout --
output: -Infinity
-- nan_math.cue --
import "math"

output: math.Mod(3, 0)
-- nan_math.stdout --
output: NaN.0

The testscript above passes as of 9394167, meaning that it reflects the current behavior. All cases except the first are clearly bugs; we produce CUE output which isn't valid.

If we want CUE to continue to not have NaN or Infinity values, we should consistently enforce that, and adjust the decoders such as YAML so that they reject inputs with them.

If we want CUE to gain NaN and Infinity values, or perhaps even constants, then we should make the appropriate adjustments to the encoders, decoders, and packages like pkg/math.

@myitcv
Copy link
Member

myitcv commented May 27, 2024

Sounds good to bottoming this out. It feels like this is a situation where we will lose fidelity between encodings: even JSON.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants