cue-lang / cue

The home of the CUE language! Validate and define text-based and dynamic configuration
https://cuelang.org
Apache License 2.0
5.02k stars 287 forks source link

evalv3: calculated embedded scalars with a default value disagree with the current evaluator when co-located with a hidden field #3415

Open jpluscplusm opened 2 weeks ago

jpluscplusm commented 2 weeks ago

What version of CUE are you using (cue version)?

$ cue version
cue version v0.10.0

go version go1.23.0
      -buildmode exe
       -compiler gc
       -trimpath true
     CGO_ENABLED 0
          GOARCH amd64
            GOOS linux
         GOAMD64 v1
cue.lang.version v0.10.0

Does this issue reproduce with the latest stable release?

0.10.0 is latest.

What did you do?

exec cue export
cmp stdout out.gold

env CUE_EXPERIMENT=evalv3
exec cue export
cmp stdout out.gold
-- file.cue --
package p

A: #A & {
  i: {
    _a + _b
    _a: 1
    _b: 10
  }
}

#A: {
  i: *0 | number
}
-- out.gold --
{
    "A": {
        "i": 11
    }
}

What did you expect to see?

A passing test.

What did you see instead?

> exec cue export
[stdout]
{
    "A": {
        "i": 11
    }
}
> cmp stdout out.gold
> env CUE_EXPERIMENT=evalv3
> exec cue export
[stdout]
{
    "A": {
        "i": 0
    }
}
> cmp stdout out.gold
diff stdout out.gold
--- stdout
+++ out.gold
@@ -1,5 +1,5 @@
 {
     "A": {
-        "i": 0
+        "i": 11
     }
 }

FAIL: /tmp/testscript261676286/evalv3.scalar.struct.default.txtar/script.txtar:6: stdout and out.gold differ
mvdan commented 1 week ago

I agree that this seems to be a regression and evalv2 is correct.

cuematthew commented 1 week ago

At the very least, you can say the evalv3 behaviour is very inconsistent: If you change the _a+_b to either just _a or _b then the default i: *0 isn't applied. By changing the embedding to the _a+_b version, the default now is applied. This seems very unlikely to be the desired behaviour.

Additionally, I don't see why the default would be applied in this case at all -- by rule U1 of https://cuelang.org/docs/reference/spec/#default-values the default 0 should be being unified with the non-default 11 and that should turn into ⊥, thus ensuring the default never features subsequently.

mpvl commented 1 week ago

This clearly is a bug in evalv3. Here is a smaller reproducer

a: {
    1 + #b
    #b: 10
}
a: *0 | number

The internal debugging info shows that the embedded scalar in a gets dropped, which means that the default is not discarded.