cue: Value.FillPath loses definition reference when encoding struct slice
What version of CUE are you using (cue version)?
$ cue version cue version (devel) linux/amd64
commit 256f1f9ee1611636fef85446ff9ea3b7d4f6b7d0
Does this issue reproduce with the latest release?
Yes.
What did you do?
I ran the following code: https://go.dev/play/p/ReEs8zpaCka
What did you expect to see?
The uses Value.FillPath to encode two Go values, both of which
contain references to the definition #Foo.
I'd expect to see the reference preserved in both cases; in other words, I'd expect to see this:
{
#Foo: string | int
structlist: [{
Name: "hello"
Val: {
x: #Foo
}
}]
map: {
hello?: {
x: #Foo
}
}
}
What did you see instead?
In most cases, the reference is preserved - for example when map[string]cue.Value is
encoded, but when encoding a list of structs, it's not.
{
#Foo: string | int
structlist: [{
Name: "hello"
Val: {
x: string | int
}
}]
map: {
hello?: {
x: #Foo
}
}
}
Note that we're seeing the literal string | int disjunction rather than the reference to #Foo.
Here's a somewhat more comprehensive illustration: https://go.dev/play/p/427QWmx4A5o, showing more variations in the data structure.
Here's the result that I see:
{
#Foo: string | int
examples: {
value?: {
x: #Foo
}
struct: {
Name: "hello"
Val?: {
x: #Foo
}
}
sliceOfValue: [{
x: #Foo
}]
sliceOfStruct: [{
Name: "hello"
Val: {
x: string | int
}
}]
mapOfValue: {
hello?: {
x: #Foo
}
}
mapOfStruct: {
hello: {
Name: "a"
Val?: {
x: #Foo
}
}
}
}
}
After discussion with @mpvl, it's clear that there's an odd discrepancy here, but it's not clear which way the discrepancy should be resolved, because the values are all notionally referring to separate #Foo instances, so perhaps either that definition should be duplicated (with a different name each time) or inlined as in the sliceOfStruct example. More investigation required.