cue-lang / cue

The home of the CUE language! Validate and define text-based and dynamic configuration
https://cuelang.org
Apache License 2.0
5.1k stars 291 forks source link

evalv3: "incDependent: already closed" with repeated disjunctions and definitions #3528

Open mvdan opened 4 days ago

mvdan commented 4 days ago
env CUE_EXPERIMENT=evalv3=0
exec cue export

env CUE_EXPERIMENT=evalv3=1
exec cue export

-- main.cue --
package p

workflows: [...#Workflow]
workflows: [test]

test: #Workflow & {}

#Workflow: {
    container: [string]: string | #container
    #container: string | {volumes?: [...string]}
}

On 12ac20b36f4de3c638cb2f2ae372df62adcfdbe2:

> env CUE_EXPERIMENT=evalv3=1
> exec cue export
[stderr]
panic: incDependent: already closed: 0xc0010d0c30 [recovered]
    panic: incDependent: already closed: 0xc0010d0c30 [recovered]
    panic: incDependent: already closed: 0xc0010d0c30

goroutine 1 gp=0xc000002380 m=19 mp=0xc000581808 [running]:
panic({0xcf6020?, 0xc001915eb0?})
    /home/mvdan/tip/src/runtime/panic.go:806 +0x168 fp=0xc0003a6208 sp=0xc0003a6158 pc=0x474688
cuelang.org/go/internal/core/adt.runTask.func1()
    /home/mvdan/src/c/cue/internal/core/adt/sched.go:695 +0x76 fp=0xc0003a6230 sp=0xc0003a6208 pc=0x72dc76
panic({0xcf6020?, 0xc001915eb0?})
    /home/mvdan/tip/src/runtime/panic.go:787 +0x132 fp=0xc0003a62e0 sp=0xc0003a6230 pc=0x474652
cuelang.org/go/internal/core/adt.runTask.func1()
    /home/mvdan/src/c/cue/internal/core/adt/sched.go:695 +0x76 fp=0xc0003a6308 sp=0xc0003a62e0 pc=0x72dc76
panic({0xcf6020?, 0xc001915eb0?})
    /home/mvdan/tip/src/runtime/panic.go:787 +0x132 fp=0xc0003a63b8 sp=0xc0003a6308 pc=0x474652
cuelang.org/go/internal/core/adt.(*closeContext).incDependent(0xc0010d0c30, 0xc000eb9860, 0xc000fc3d10?, 0x0?)
    /home/mvdan/src/c/cue/internal/core/adt/fields.go:562 +0xa6 fp=0xc0003a6400 sp=0xc0003a63b8 pc=0x725ec6
cuelang.org/go/internal/core/adt.(*closeContext).getKeyedCC(0xc0010d0e10, 0xc000eb9860, 0xc0010d03c0, {0x0?, 0x0?, 0x0?, 0xc001919d40?}, 0x2, 0x1)
    /home/mvdan/src/c/cue/internal/core/adt/fields.go:414 +0x30c fp=0xc0003a64e0 sp=0xc0003a6400 pc=0x72540c
[...]
mpvl commented 4 days ago

Slightly simplified:

a?: #A
a:  #A & {}
#A: {
    A: [string]: 1 | #a
    #a: 2 | {v: 1}
}

This does not panic, but results in a counter issue, which may help understanding the problem:

a?: #A
a:  #A & {}
#A: {
    b: 1 | a
    a: 2 | {v: 1}
}
mpvl commented 1 day ago

Update: The optional field and conjunction in the above example are necessary to disable the deduping, causing #A to be unified with itself. So a reducer that gets more to the meat of the problem is:

{v: 1} | (2 | 3)
{v: 1} | (2 | 3)

So it happens when a disjunction with nested disjunctions gets unified with itself. One of the disjuncts needs to have a field.

mpvl commented 1 day ago

Narrowing it down further: the field needs to be defined in the first disjunction, the nested disjunction needs to be defined in the second:

{v: 1} | 2
(4|5) | 3

counter issue