Skip to content

Commit 06141e4

Browse files
committed
internal/core/debug: add cycle detector
Sometimes nodes are shared (using structure sharing) that have a structural cycle without reporting on that structural cycle. This caused printing to hang. This change detects such cases and modifies to output to inform about such cycles. Issue #2850 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: Iba74c91729507a4782c7f5902ef2ac6ed2770716 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1201896 Reviewed-by: Matthew Sackman <[email protected]> Unity-Result: CUE porcuepine <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 4140094 commit 06141e4

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

internal/core/adt/unify.go

+2
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ func (n *nodeContext) updateScalar() {
438438
}
439439

440440
func (n *nodeContext) completeAllArcs(needs condition, mode runMode) bool {
441+
// TODO: this can go when lookup vs evaluation distinction
442+
// has been improved.
441443
if n.node.status == evaluatingArcs {
442444
// NOTE: this was an "incomplete" error pre v0.6. If this is a problem
443445
// we could make this a CycleError. Technically, this may be correct,

internal/core/debug/compact.go

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func (w *compactPrinter) node(n adt.Node) {
8989
case *adt.Vertex:
9090
if v, ok := w.printShared(x); !ok {
9191
w.node(v)
92+
w.popVertex()
9293
}
9394

9495
case adt.Value:

internal/core/debug/debug.go

+27
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ type printer struct {
7070
indent string
7171
cfg *Config
7272

73+
// keep track of vertices to avoid cycles.
74+
stack []*adt.Vertex
75+
7376
// modes:
7477
// - show vertex
7578
// - show original conjuncts
@@ -144,9 +147,32 @@ func (w *printer) printShared(v *adt.Vertex) (x *adt.Vertex, ok bool) {
144147
w.shared(s)
145148
return v, true
146149
}
150+
if !w.pushVertex(v) {
151+
if s != nil {
152+
w.shared(s)
153+
w.string(" =>")
154+
}
155+
w.shared(v)
156+
return v, true
157+
}
147158
return v, false
148159
}
149160

161+
func (w *printer) pushVertex(v *adt.Vertex) bool {
162+
for _, x := range w.stack {
163+
if x == v {
164+
w.string("<TODO: unmarked structural cycle>")
165+
return false
166+
}
167+
}
168+
w.stack = append(w.stack, v)
169+
return true
170+
}
171+
172+
func (w *printer) popVertex() {
173+
w.stack = w.stack[:len(w.stack)-1]
174+
}
175+
150176
func (w *printer) shortError(errs errors.Error) {
151177
for {
152178
msg, args := errs.Msg()
@@ -201,6 +227,7 @@ func (w *printer) node(n adt.Node) {
201227
if ok {
202228
return
203229
}
230+
defer w.popVertex()
204231

205232
var kind adt.Kind
206233
if x.BaseValue != nil {

0 commit comments

Comments
 (0)