cue icon indicating copy to clipboard operation
cue copied to clipboard

Nested definition with default value takes the default value

Open b4nst opened this issue 2 years ago • 4 comments

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?

playground

#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.

b4nst avatar Nov 10 '23 09:11 b4nst

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.

uhthomas avatar Nov 10 '23 12:11 uhthomas

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.

rogpeppe avatar Nov 10 '23 17:11 rogpeppe

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.

b4nst avatar Nov 12 '23 23:11 b4nst

This is resolved as of v0.15.0; I bisected the fix to a1cfb1ca4e750db0925510ac35b3433eae768064. I'll close this with a test.

mvdan avatar Dec 07 '25 19:12 mvdan