Nested definition with default value takes the default value
What version of CUE are you using (cue version)?
$ cue version
cue version (devel)
go version go1.20.7
-buildmode exe
-compiler gc
CGO_ENABLED 1
GOARCH arm64
GOOS darwin
Does this issue reproduce with the latest stable release?
Yes, also reproduces on the playground.
What did you do?
#Foo: {
bar: int
opt?: int
} | *{
opt: int
}
foo: #Foo
foo: bar: 0
{
foo: #Foo
}
What did you expect to see?
foo: {
bar: 0
}
What did you see instead?
foo: {
bar: 0
opt: int
}
If l.12 is commented out, this is the result we get.
Echoing what I wrote on slack, cue def produces:
#Foo: {
bar: int
opt?: int
} | *{
opt: int
}
foo: #Foo & #Foo & {
bar: 0
}
Which when evaluated, does not produce the unexpected value.
This is clearly a bug of some sort: in general in CUE, embedding {X} should be identical to embedding X but here, if we remove the {} around {foo: #Foo}, it changes the behavior.
Also, the output containing both bar and opt is also clearly wrong behavior AFAICS, because the only place that opt is defined is in the branch of #Foo that does not contain bar.
Btw this can be somehow worked around for this use case by introducing bar as a forbidden field in the default value
#Foo: {
bar: int
opt?: int
} | *{
opt: int
bar?: _|_ // <- here
}
foo: #Foo
foo: bar: 0
{
foo: #Foo
}
I don't think it covers all the cases, but posting that here in case it helps.
This is resolved as of v0.15.0; I bisected the fix to a1cfb1ca4e750db0925510ac35b3433eae768064. I'll close this with a test.