cue icon indicating copy to clipboard operation
cue copied to clipboard

cue: Value.FillPath loses definition reference when encoding struct slice

Open rogpeppe opened this issue 3 years ago • 2 comments

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.

rogpeppe avatar May 25 '22 17:05 rogpeppe

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
				}
			}
		}
	}
}

rogpeppe avatar May 25 '22 18:05 rogpeppe

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.

rogpeppe avatar May 31 '22 11:05 rogpeppe