cue icon indicating copy to clipboard operation
cue copied to clipboard

encoding/yaml: "unexpected zero path length" when referencing a key key of a struct through a for clause

Open addreas opened this issue 2 years ago • 1 comments

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

$ cue version
cue version v0.0.0-20220808083940-b4d1b16ccf89

       -compiler gc
     CGO_ENABLED 1
          GOARCH amd64
            GOOS linux
         GOAMD64 v1
             vcs git
    vcs.revision b4d1b16ccf8944599eec6870da400d2b56da979b
        vcs.time 2022-08-08T08:39:40Z
    vcs.modified true

Does this issue reproduce with the latest release?

No

What did you do?

Using this kind of pattern to specify constraints in bulk (concrete example):

import "encoding/yaml"

t: {
	for key, value in {test: _} {
		[string]: "": key
	}

	item: {}
}

encode: yaml.Marshal(t.item)

What did you expect to see?

Successful cue vet, cue def, etc.

What did you see instead?

error in call to encoding/yaml.Marshal: unexpected zero path length:
    ./test.cue:11:9

Hitting this panic, when the d *depData contains a dstNode where d.dstNode.BaseValue is &adt.String{Src:(*ast.ForClause)(0xc000048cc0), Str:"test", RE:(*regexp.Regexp)(nil)}. Replacing the panic with a return seems to make it work, as does just removing it completely. Not sure what other things might break with that change though.

addreas avatar Aug 09 '22 14:08 addreas

What's very interesting is that this "works" (by some definition of that word) in the playground:

https://cuelang.org/play/?id=ORg4oJRp_2_0#cue@export@cue

Marking as comprehension related.

myitcv avatar Aug 11 '22 12:08 myitcv

Using the tip version of the cue tool, which reports its version as

cue version v0.4.4-0.20220928102958-cad3f2394c59

       -compiler gc
     CGO_ENABLED 1
          GOARCH amd64
            GOOS darwin
         GOAMD64 v1

I run into the same problem when calling on yaml.MarshalStream, passing it a list built up from a comprehension. Removing the comprehension and supplying the same resulting list items directly eliminates the problem.

Here's a reduced example that fails in the aforementioned version, but succeeds with version 0.4.3:

import (
	"encoding/yaml"
)

yaml.MarshalStream([
	for k, v in {
		"a": type: "t1"
		"b": type: "t2"
	} {
		{
			name: k
			type: v.type
		}
	},
])

seh avatar Sep 28 '22 13:09 seh

Note that in both @addreas's and my examples, if you remove the call to the YAML marshaling function, cue export succeeds in producing the expected output (just not as a string with YAML content). In other words, the problem doesn't seem to be the data supplied to the function call.

seh avatar Sep 28 '22 14:09 seh

Interestingly, using a comprehension over a list rather than a struct works fine:

import (
	"encoding/yaml"
)

yaml.MarshalStream([
	for v in [
		{
			name: "a"
			type: "t1"
		},
		{
			name: "b"
			type: "t2"
		},
	] {
		{
			name: v.name
			type: v.type
		}
	},
])

Yes, I see that that's just an identity projection.

seh avatar Sep 28 '22 14:09 seh