internal/core/adt: fix special cycle condition
Where node could be used with a 0 status.
This will be fixed when cycle detection is fixed, which
can be done if structure sharing is implemented.
Change-Id: I001a4e4c2b880c2011f36ee34af4966114f1bca9
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8561
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar b/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar
index e2685bc..7fa3fa7 100644
--- a/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar
+++ b/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar
@@ -1,7 +1,20 @@
-# DO NOT EDIT; generated by go run testdata/gen.go
-#
#name: resolved self-reference cycles with disjunction
#evalPartial
+
+// TODO(cycle)
+//
+// Some of these examples used to work, but the changes corresponding to this
+// addition, it ceased to do so. Fixing these cycle issues seemed more
+// important than keeping this esoteric case working, which was already broken
+// in the last release anyway.
+//
+// Reproducer of underlying problem. Still works, but triggers unexpected
+// condition.
+//
+// xb1: xb2
+// xb2: xb3
+// xb3: xb2 + 0
+
-- in.cue --
// The second disjunct in xa1 is not resolvable and can be
// eliminated:
@@ -174,10 +187,16 @@
xa2: (int){ 8 }
xa3: (int){ 6 }
xa4: (int){ 10 }
- xb1: (int){ 8 }
- xb2: (int){ 8 }
- xb3: (int){ 6 }
- xb4: (int){ 10 }
+ xb1: (int){ 9 }
+ xb2: (_|_){
+ // [incomplete] xb2: unresolved disjunction 6 | 9 (type int):
+ // ./in.cue:18:6
+ }
+ xb3: (int){ |((int){ 6 }, (int){ 9 }) }
+ xb4: (_|_){
+ // [incomplete] xb2: unresolved disjunction 6 | 9 (type int):
+ // ./in.cue:18:6
+ }
xc1: (int){ |((int){ 8 }, (int){ 9 }) }
xc2: (int){ 8 }
xc3: (_|_){
@@ -220,10 +239,16 @@
// ./in.cue:45:6
// ./in.cue:45:10
}
- xf1: (int){ 8 }
- xf2: (int){ 8 }
- xf3: (int){ 6 }
- xf4: (int){ 10 }
+ xf1: (int){ 9 }
+ xf2: (_|_){
+ // [incomplete] xf2: unresolved disjunction 6 | 9 (type int):
+ // ./in.cue:52:6
+ }
+ xf3: (int){ |((int){ 6 }, (int){ 9 }) }
+ xf4: (_|_){
+ // [incomplete] xf2: unresolved disjunction 6 | 9 (type int):
+ // ./in.cue:52:6
+ }
z1: (int){ |((int){ 11 }, (int){ 13 }) }
z2: (int){ 10 }
z3: (_|_){
diff --git a/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar b/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar
index 60e48f6..c37f9fa 100644
--- a/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar
+++ b/cue/testdata/cycle/052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar
@@ -143,7 +143,7 @@
xa4: (int){ 10 }
xb1: (int){ 8 }
xb2: (int){ 8 }
- xb3: (int){ 6 }
+ xb3: (int){ |(*(int){ 6 }, (int){ 9 }) }
xb4: (int){ 10 }
xc1: (int){ |(*(int){ 8 }, (int){ 9 }) }
xc2: (int){ 8 }
diff --git a/internal/core/adt/eval.go b/internal/core/adt/eval.go
index 3e03ae0..38c0c94 100644
--- a/internal/core/adt/eval.go
+++ b/internal/core/adt/eval.go
@@ -184,6 +184,7 @@
return
case EvaluatingArcs:
+ Assertf(v.status > 0, "unexpected status %d", v.status)
return
case 0:
@@ -1321,6 +1322,16 @@
closeInfo = closeInfo.SpawnRef(arc, IsDef(x), x)
+ if arc.status == 0 && !inline {
+ // This is a rare condition, but can happen in certain
+ // evaluation orders. Unfortunately, adding this breaks
+ // resolution of cyclic mutually referring disjunctions. But it
+ // is necessary to prevent lookups in unevaluated structs.
+ // TODO(cycles): this can probably most easily be fixed with a
+ // having a more recursive implementation.
+ n.ctx.Unify(arc, AllArcs)
+ }
+
for _, c := range arc.Conjuncts {
var a []*Vertex
if env != nil {