diff --git a/cue/testdata/cycle/evaluate.txtar b/cue/testdata/cycle/evaluate.txtar index 99fb7f08074..36d568e2a26 100644 --- a/cue/testdata/cycle/evaluate.txtar +++ b/cue/testdata/cycle/evaluate.txtar @@ -127,6 +127,7 @@ Conjuncts: 299 Disjuncts: 192 -- out/evalalpha -- Errors: +closeCycle.c: structural cycle printCycle.a.X: structural cycle structCycle.c: structural cycle letCycleOK.t2.a.X: structural cycle: @@ -138,8 +139,6 @@ disjunctionCycle.b: cannot use 1 (type int) as type list: ./in.cue:56:9 b: structural cycle: ./in.cue:62:6 -closeCycle.c: structural cycle: - ./in.cue:73:11 structural cycle: ./in.cue:85:12 listAddCycle.c: structural cycle: @@ -252,17 +251,15 @@ Result: } closeCycle: (_|_){ // [structural cycle] - a: (_|_){ - // [structural cycle] closeCycle.c: structural cycle: - // ./in.cue:73:11 - } + a: ~(closeCycle.b) b: (_|_){ - // [structural cycle] closeCycle.c: structural cycle: - // ./in.cue:73:11 + // [structural cycle] + d: (_|_){ + // [structural cycle] closeCycle.c: structural cycle + } } c: (_|_){ - // [structural cycle] closeCycle.c: structural cycle: - // ./in.cue:73:11 + // [structural cycle] closeCycle.c: structural cycle } } structCycle: (_|_){ @@ -353,7 +350,7 @@ Result: diff old new --- old +++ new -@@ -1,50 +1,50 @@ +@@ -1,50 +1,49 @@ Errors: -closeCycle.a: structural cycle -closeCycle.b.d: structural cycle @@ -368,6 +365,7 @@ diff old new -disjunctionCycle.a: cannot use 1 (type int) as type list: - ./in.cue:56:5 - ./in.cue:56:9 ++closeCycle.c: structural cycle +printCycle.a.X: structural cycle +structCycle.c: structural cycle +letCycleOK.t2.a.X: structural cycle: @@ -382,7 +380,7 @@ diff old new - ./in.cue:56:9 b: structural cycle: ./in.cue:62:6 - closeCycle.c: structural cycle: +-closeCycle.c: structural cycle: - ./in.cue:73:15 -structCycle.c: structural cycle: - ./in.cue:79:14 @@ -390,7 +388,6 @@ diff old new - ./in.cue:85:11 -printCycle.a.X.X: structural cycle: - ./in.cue:113:6 -+ ./in.cue:73:11 +structural cycle: + ./in.cue:85:12 +listAddCycle.c: structural cycle: @@ -431,7 +428,7 @@ diff old new } } } -@@ -59,20 +59,16 @@ +@@ -59,20 +58,16 @@ // [structural cycle] letCycleFail.t1.a.X: structural cycle } c: (_|_){ @@ -462,7 +459,7 @@ diff old new } x: (struct){ y: (string){ "" } -@@ -88,17 +84,17 @@ +@@ -88,17 +83,17 @@ disjunctionCycle: (_|_){ // [eval] a: (_|_){ @@ -491,7 +488,7 @@ diff old new // ./in.cue:56:5 // ./in.cue:56:9 } -@@ -124,80 +120,79 @@ +@@ -124,80 +119,77 @@ } b: (struct){ } @@ -503,7 +500,7 @@ diff old new } closeCycle: (_|_){ // [structural cycle] - a: (_|_){ +- a: (_|_){ - // [structural cycle] closeCycle.a: structural cycle - } - b: (_|_){ @@ -515,16 +512,15 @@ diff old new - c: (_|_){ - // [structural cycle] closeCycle.c: structural cycle: - // ./in.cue:73:15 -+ // [structural cycle] closeCycle.c: structural cycle: -+ // ./in.cue:73:11 -+ } ++ a: ~(closeCycle.b) + b: (_|_){ -+ // [structural cycle] closeCycle.c: structural cycle: -+ // ./in.cue:73:11 ++ // [structural cycle] ++ d: (_|_){ ++ // [structural cycle] closeCycle.c: structural cycle ++ } + } + c: (_|_){ -+ // [structural cycle] closeCycle.c: structural cycle: -+ // ./in.cue:73:11 ++ // [structural cycle] closeCycle.c: structural cycle } } structCycle: (_|_){ @@ -622,7 +618,7 @@ diff old new } } closeFail: (_|_){ -@@ -207,21 +202,22 @@ +@@ -207,21 +199,22 @@ } x: (_|_){ // [eval] diff --git a/cue/testdata/cycle/inline_non_recursive.txtar b/cue/testdata/cycle/inline_non_recursive.txtar index 116f5335fd0..0a7ca8ad733 100644 --- a/cue/testdata/cycle/inline_non_recursive.txtar +++ b/cue/testdata/cycle/inline_non_recursive.txtar @@ -58,19 +58,45 @@ issue1708: { k20: (#add10 & {in: k10}).out k30: (#add10 & {in: k20}).out } - +-- issue3182.cue -- +issue3182: { + first: t1: { + x: { a: x }.a + } + first: t2: { + x: { a: b: x }.a + } + second: { + { t: x }.t.y + x: y: x: y: a: 1 + } + third: { + { + p: { + x: p + y: 1 + } + }.p.x.y + } +} -- out/evalalpha/stats -- -Leaks: 209 +Leaks: 250 Freed: 0 Reused: 0 -Allocs: 209 +Allocs: 250 Retain: 0 -Unifications: 194 -Conjuncts: 1034 +Unifications: 240 +Conjuncts: 1277 Disjuncts: 0 -- out/evalalpha -- -(struct){ +Errors: +issue3182.first.t2.x.b: structural cycle: + ./issue3182.cue:6:6 + +Result: +(_|_){ + // [structural cycle] ok1: (struct){ f: (struct){ in: (number){ number } @@ -133,34 +159,75 @@ Disjuncts: 0 k20: (int){ 20 } k30: (int){ 30 } } + issue3182: (_|_){ + // [structural cycle] + first: (_|_){ + // [structural cycle] + t1: (struct){ + x: (_){ _ } + } + t2: (_|_){ + // [structural cycle] + x: (_|_){ + // [structural cycle] + b: (_|_){ + // [structural cycle] issue3182.first.t2.x.b: structural cycle: + // ./issue3182.cue:6:6 + } + } + } + } + second: (struct){ + x: (struct){ + y: (struct){ + x: (struct){ + y: (struct){ + a: (int){ 1 } + } + } + a: (int){ 1 } + } + } + a: (int){ 1 } + } + third: (int){ 1 } + } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ --Leaks: 291 --Freed: 389 --Reused: 379 --Allocs: 301 --Retain: 1047 -+Leaks: 209 +-Leaks: 306 +-Freed: 405 +-Reused: 401 +-Allocs: 310 +-Retain: 1066 ++Leaks: 250 +Freed: 0 +Reused: 0 -+Allocs: 209 ++Allocs: 250 +Retain: 0 --Unifications: 680 --Conjuncts: 2709 --Disjuncts: 1414 -+Unifications: 194 -+Conjuncts: 1034 +-Unifications: 711 +-Conjuncts: 2759 +-Disjuncts: 1446 ++Unifications: 240 ++Conjuncts: 1277 +Disjuncts: 0 -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new -@@ -48,14 +48,12 @@ +@@ -1,5 +1,6 @@ + Errors: +-issue3182.first.t2.x.b: structural cycle ++issue3182.first.t2.x.b: structural cycle: ++ ./issue3182.cue:6:6 + + Result: + (_|_){ +@@ -53,14 +54,12 @@ // [incomplete] issue1708.#add10.a10.o: non-concrete value number in operand to +: // ./in.cue:52:20 // ./in.cue:51:7 @@ -176,21 +243,36 @@ diff old new } } k00: (int){ 0 } +@@ -80,7 +79,8 @@ + x: (_|_){ + // [structural cycle] + b: (_|_){ +- // [structural cycle] issue3182.first.t2.x.b: structural cycle ++ // [structural cycle] issue3182.first.t2.x.b: structural cycle: ++ // ./issue3182.cue:6:6 + } + } + } -- diff/todo/p3 -- Error positions. Incorrect path due to structure sharing. -- out/eval/stats -- -Leaks: 291 -Freed: 389 -Reused: 379 -Allocs: 301 -Retain: 1047 +Leaks: 306 +Freed: 405 +Reused: 401 +Allocs: 310 +Retain: 1066 -Unifications: 680 -Conjuncts: 2709 -Disjuncts: 1414 +Unifications: 711 +Conjuncts: 2759 +Disjuncts: 1446 -- out/eval -- -(struct){ +Errors: +issue3182.first.t2.x.b: structural cycle + +Result: +(_|_){ + // [structural cycle] ok1: (struct){ f: (struct){ in: (number){ number } @@ -255,6 +337,38 @@ Disjuncts: 1414 k20: (int){ 20 } k30: (int){ 30 } } + issue3182: (_|_){ + // [structural cycle] + first: (_|_){ + // [structural cycle] + t1: (struct){ + x: (_){ _ } + } + t2: (_|_){ + // [structural cycle] + x: (_|_){ + // [structural cycle] + b: (_|_){ + // [structural cycle] issue3182.first.t2.x.b: structural cycle + } + } + } + } + second: (struct){ + x: (struct){ + y: (struct){ + x: (struct){ + y: (struct){ + a: (int){ 1 } + } + } + a: (int){ 1 } + } + } + a: (int){ 1 } + } + third: (int){ 1 } + } } -- out/compile -- --- in.cue @@ -368,3 +482,46 @@ Disjuncts: 1414 }).out } } +--- issue3182.cue +{ + issue3182: { + first: { + t1: { + x: { + a: 〈1;x〉 + }.a + } + } + first: { + t2: { + x: { + a: { + b: 〈2;x〉 + } + }.a + } + } + second: { + { + t: 〈1;x〉 + }.t.y + x: { + y: { + x: { + y: { + a: 1 + } + } + } + } + } + third: { + { + p: { + x: 〈1;p〉 + y: 1 + } + }.p.x.y + } + } +} diff --git a/cue/testdata/cycle/structural.txtar b/cue/testdata/cycle/structural.txtar index 307fe4bf62e..aa6ba1a0588 100644 --- a/cue/testdata/cycle/structural.txtar +++ b/cue/testdata/cycle/structural.txtar @@ -621,7 +621,6 @@ b7.b.0.0: conflicting values 1 and [a] (mismatched types int and list): b7.b.0.0.0: structural cycle c1.a.c: structural cycle d1.r: structural cycle -d3.x.0: structural cycle e1.a.c: structural cycle e1.b.c: structural cycle e2.a.c: structural cycle @@ -686,6 +685,8 @@ patternFail.issue2374.a.b: structural cycle shortPathFail.elipsis.t2.Foo.ref: structural cycle withLetFail._schema_1: structural cycle z1.z.g.h: structural cycle +d3.x.0: structural cycle: + ./in.cue:317:13 3: structural cycle: ./in.cue:371:9 e4.a.0.0: cannot combine regular field "c" with [1,{c:1} & (a|{}) & [{c:1}]]: @@ -1273,12 +1274,14 @@ Result: b: (_|_){ // [structural cycle] c: (_|_){ - // [structural cycle] d3.x.0: structural cycle + // [structural cycle] d3.x.0: structural cycle: + // ./in.cue:317:13 } } } indirect: (_|_){ - // [structural cycle] d3.x.0: structural cycle + // [structural cycle] d3.x.0: structural cycle: + // ./in.cue:317:13 } } } @@ -1775,7 +1778,7 @@ Result: diff old new --- old +++ new -@@ -4,22 +4,26 @@ +@@ -4,22 +4,25 @@ b12b.#list.tail: structural cycle b13.root.a.0.0: structural cycle b14.root.b.1.1: structural cycle @@ -1805,11 +1808,10 @@ diff old new +b7.b.0.0.0: structural cycle +c1.a.c: structural cycle +d1.r: structural cycle -+d3.x.0: structural cycle e1.a.c: structural cycle e1.b.c: structural cycle e2.a.c: structural cycle -@@ -32,61 +36,84 @@ +@@ -32,61 +35,86 @@ ./in.cue:403:5 ./in.cue:404:5 e3.b.c: structural cycle @@ -1892,6 +1894,8 @@ diff old new - ./in.cue:301:26 -d3.x.indirect: structural cycle: - ./in.cue:316:12 ++d3.x.0: structural cycle: ++ ./in.cue:317:13 +3: structural cycle: + ./in.cue:371:9 +e4.a.0.0: cannot combine regular field "c" with [1,{c:1} & (a|{}) & [{c:1}]]: @@ -1921,7 +1925,7 @@ diff old new Result: (_|_){ -@@ -128,10 +155,7 @@ +@@ -128,10 +156,7 @@ a7: (struct){ a: (string){ "foo" } b: (struct){ @@ -1933,7 +1937,7 @@ diff old new y: (string){ "foo" } } c: (struct){ -@@ -168,11 +192,17 @@ +@@ -168,11 +193,17 @@ } } b4: (_|_){ @@ -1956,7 +1960,7 @@ diff old new } } x: (_|_){ -@@ -240,10 +270,9 @@ +@@ -240,10 +271,9 @@ // [eval] 0: (_|_){ // [eval] b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list): @@ -1968,7 +1972,7 @@ diff old new 0: (_|_){ // [structural cycle] b6.b.a.0.0: structural cycle } -@@ -261,11 +290,20 @@ +@@ -261,11 +291,20 @@ } } b7: (_|_){ @@ -1994,7 +1998,7 @@ diff old new } } a: (_|_){ -@@ -276,9 +314,7 @@ +@@ -276,9 +315,7 @@ } } b8: (struct){ @@ -2005,7 +2009,7 @@ diff old new a: (struct){ f: (string){ string } } -@@ -304,7 +340,7 @@ +@@ -304,7 +341,7 @@ #ref: (#struct){ ref: (string){ string } } @@ -2014,7 +2018,7 @@ diff old new c: (#list){ 0: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } -@@ -327,7 +363,13 @@ +@@ -327,7 +364,13 @@ }) } } c: (#struct){ @@ -2029,7 +2033,7 @@ diff old new } d: (struct){ d: (struct){ -@@ -337,9 +379,7 @@ +@@ -337,9 +380,7 @@ } b11: (struct){ #list: (#struct){ @@ -2040,7 +2044,7 @@ diff old new } } b12: (struct){ -@@ -356,7 +396,11 @@ +@@ -356,7 +397,11 @@ value: (int){ 3 } tail: (#struct){ value: (int){ 4 } @@ -2053,7 +2057,7 @@ diff old new sum: (int){ 4 } } sum: (int){ 7 } -@@ -428,10 +472,7 @@ +@@ -428,10 +473,7 @@ link: (#struct){ a: (#struct){ two: (#struct){ @@ -2065,7 +2069,7 @@ diff old new } } } -@@ -505,10 +546,7 @@ +@@ -505,10 +547,7 @@ link: (#struct){ a: (#list){ 0: (#struct){ @@ -2077,7 +2081,7 @@ diff old new } } } -@@ -578,12 +616,7 @@ +@@ -578,12 +617,7 @@ b: (struct){ } c: (_|_){ @@ -2091,7 +2095,7 @@ diff old new } } } -@@ -599,56 +632,26 @@ +@@ -599,56 +633,26 @@ // [structural cycle] h: (int){ int } t: (_|_){ @@ -2168,7 +2172,7 @@ diff old new } } } -@@ -666,28 +669,25 @@ +@@ -666,28 +670,27 @@ } x: (_|_){ // [structural cycle] @@ -2179,7 +2183,8 @@ diff old new // [structural cycle] c: (_|_){ - // [structural cycle] d3.x.a.b.c: structural cycle -+ // [structural cycle] d3.x.0: structural cycle ++ // [structural cycle] d3.x.0: structural cycle: ++ // ./in.cue:317:13 } } } @@ -2188,7 +2193,8 @@ diff old new - // ./in.cue:316:12 - } - i: (int){ 0 } -+ // [structural cycle] d3.x.0: structural cycle ++ // [structural cycle] d3.x.0: structural cycle: ++ // ./in.cue:317:13 + } } } @@ -2202,7 +2208,7 @@ diff old new #List: (#struct){ Next: (null){ null } } -@@ -696,9 +696,7 @@ +@@ -696,9 +699,7 @@ // [structural cycle] t1: (struct){ #Foo: (#struct){ @@ -2213,7 +2219,7 @@ diff old new } } t2: (_|_){ -@@ -706,10 +704,7 @@ +@@ -706,10 +707,7 @@ Foo: (_|_){ // [structural cycle] ref: (_|_){ @@ -2225,7 +2231,7 @@ diff old new } } } -@@ -716,9 +711,7 @@ +@@ -716,9 +714,7 @@ } comprehension: (struct){ #list: (#struct){ @@ -2236,7 +2242,7 @@ diff old new } } } -@@ -740,12 +733,11 @@ +@@ -740,12 +736,11 @@ schema: (_|_){ // [structural cycle] next: (_|_){ @@ -2251,7 +2257,7 @@ diff old new } } fieldsSumInfinite: (_|_){ -@@ -756,7 +748,8 @@ +@@ -756,7 +751,8 @@ fries: (float){ 2.00 } sprite: (float){ 1.00 } total: (_|_){ @@ -2261,7 +2267,7 @@ diff old new } } } -@@ -771,9 +764,7 @@ +@@ -771,9 +767,7 @@ head: (int){ 3 } tail: (struct){ head: (int){ 2 } @@ -2272,7 +2278,7 @@ diff old new } } } -@@ -813,11 +804,12 @@ +@@ -813,11 +807,12 @@ // [eval] e3.a: conflicting values [a] and {c:a} (mismatched types list and struct): // ./in.cue:400:5 // ./in.cue:401:5 @@ -2290,7 +2296,7 @@ diff old new } } b: (_|_){ -@@ -824,11 +816,12 @@ +@@ -824,11 +819,12 @@ // [eval] e3.b: conflicting values [b] and {c:b} (mismatched types list and struct): // ./in.cue:403:5 // ./in.cue:404:5 @@ -2308,7 +2314,7 @@ diff old new } } } -@@ -837,41 +830,63 @@ +@@ -837,41 +833,63 @@ a: (_|_){ // [eval] 0: (_|_){ @@ -2403,7 +2409,7 @@ diff old new } } } -@@ -894,19 +909,14 @@ +@@ -894,19 +912,14 @@ y: (_|_){ // [eval] 0: (_|_){ @@ -2426,7 +2432,7 @@ diff old new } 1: (int){ 1 } } -@@ -916,19 +926,14 @@ +@@ -916,19 +929,14 @@ y: (_|_){ // [eval] 0: (_|_){ @@ -2449,7 +2455,7 @@ diff old new } 1: (int){ 1 } } -@@ -981,7 +986,10 @@ +@@ -981,7 +989,10 @@ head: (int){ 3 } tail: (struct){ head: (int){ 4 } @@ -2461,7 +2467,7 @@ diff old new } } } -@@ -995,7 +1003,10 @@ +@@ -995,7 +1006,10 @@ head: (int){ 2 } tail: (struct){ head: (int){ 3 } @@ -2473,7 +2479,7 @@ diff old new } } } -@@ -1009,8 +1020,12 @@ +@@ -1009,8 +1023,12 @@ head: (int){ 2 } tail: (struct){ |((struct){ head: (int){ 3 } @@ -2488,7 +2494,7 @@ diff old new }, (struct){ head: (int){ 3 } }) } -@@ -1032,9 +1047,7 @@ +@@ -1032,9 +1050,7 @@ // [structural cycle] f: (_|_){ // [structural cycle] @@ -2499,7 +2505,7 @@ diff old new } g: (_|_){ // [structural cycle] -@@ -1055,10 +1068,7 @@ +@@ -1055,10 +1071,7 @@ x: (_){ _ } y: (_){ _ } } @@ -2511,7 +2517,7 @@ diff old new } } t2: (struct){ -@@ -1071,10 +1081,7 @@ +@@ -1071,10 +1084,7 @@ x: (_){ _ } y: (_){ _ } } @@ -2523,7 +2529,7 @@ diff old new } } t3: (struct){ -@@ -1089,16 +1096,8 @@ +@@ -1089,16 +1099,8 @@ y: (_){ _ } z: (_){ _ } } @@ -2542,7 +2548,7 @@ diff old new } } t4: (struct){ -@@ -1114,51 +1113,11 @@ +@@ -1114,51 +1116,11 @@ y: (_){ _ } z: (_){ _ } } @@ -2599,7 +2605,7 @@ diff old new } } t5: (struct){ -@@ -1169,6 +1128,7 @@ +@@ -1169,6 +1131,7 @@ } } C: (struct){ @@ -2607,7 +2613,7 @@ diff old new y: (struct){ y: (_|_){ // [incomplete] crossRefNoCycle.t5.C.y.y: undefined field: x: -@@ -1175,12 +1135,6 @@ +@@ -1175,12 +1138,6 @@ // ./in.cue:544:8 } } @@ -2620,7 +2626,7 @@ diff old new } } } -@@ -1203,19 +1157,19 @@ +@@ -1203,19 +1160,19 @@ } } n4: (struct){ diff --git a/cue/testdata/eval/conjuncts.txtar b/cue/testdata/eval/conjuncts.txtar index 0104c8e4e93..718bee28c69 100644 --- a/cue/testdata/eval/conjuncts.txtar +++ b/cue/testdata/eval/conjuncts.txtar @@ -69,14 +69,14 @@ issue2355: { } -- out/evalalpha/stats -- -Leaks: 192 +Leaks: 191 Freed: 24 Reused: 24 -Allocs: 192 +Allocs: 191 Retain: 0 -Unifications: 46 -Conjuncts: 372 +Unifications: 44 +Conjuncts: 361 Disjuncts: 126 -- out/evalalpha -- Errors: @@ -168,17 +168,17 @@ diff old new -Reused: 59 -Allocs: 18 -Retain: 22 -+Leaks: 192 ++Leaks: 191 +Freed: 24 +Reused: 24 -+Allocs: 192 ++Allocs: 191 +Retain: 0 -Unifications: 45 -Conjuncts: 135 -Disjuncts: 86 -+Unifications: 46 -+Conjuncts: 372 ++Unifications: 44 ++Conjuncts: 361 +Disjuncts: 126 -- diff/-out/evalalpha<==>+out/eval -- diff old new diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go index 5a38bfd3214..d6b867a70b7 100644 --- a/internal/core/adt/context.go +++ b/internal/core/adt/context.go @@ -909,6 +909,10 @@ func (c *OpContext) unifyNode(v Expr, state combinedFlags) (result Value) { if c.isDevVersion() { if n := v.getState(c); n != nil { + // A lookup counts as new structure. See the commend in Section + // "Lookups in inline cycles" in cycle.go. + n.hasNonCycle = true + // Always yield to not get spurious errors. n.process(arcTypeKnown, yield) } diff --git a/internal/core/adt/cycle.go b/internal/core/adt/cycle.go index 520f56c156d..e9725490e73 100644 --- a/internal/core/adt/cycle.go +++ b/internal/core/adt/cycle.go @@ -315,6 +315,16 @@ package adt // structural cycles to such nodes as "reference cycles". As pattern constraints // are optional, it is safe to ignore such errors. // +// ### Lookups in inline cycles +// +// A lookup, especially in inline cycles, should be considered evidence of +// non-cyclicity. Consider the following example: +// +// { p: { x: p, y: 1 } }.p.x.y +// +// without considering a lookup as evidence of non-cyclicity, this would be +// resulting in a structural cycle. +// // ## CORRECTNESS // // ### The algorithm will terminate diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go index 68c26287ed7..5071fca7099 100644 --- a/internal/core/adt/expr.go +++ b/internal/core/adt/expr.go @@ -110,7 +110,7 @@ func (x *StructLit) evaluate(c *OpContext, state combinedFlags) Value { // // v.completeArcs(c, state) - v.CompleteArcs(c) + v.CompleteArcsOnly(c) return v } @@ -2097,7 +2097,9 @@ func (x *ForClause) yield(s *compState) { if c.isDevVersion() { // TODO(evalv3): See comment in StructLit.evaluate. - c.require(a, arcTypeKnown) + if state := a.getState(c); state != nil { + state.process(arcTypeKnown, attemptOnly) + } } else { if !a.isDefined() { a.Finalize(c) diff --git a/internal/core/adt/share.go b/internal/core/adt/share.go index 7da9615912b..2f9c4816f52 100644 --- a/internal/core/adt/share.go +++ b/internal/core/adt/share.go @@ -88,6 +88,7 @@ func (n *nodeContext) share(c Conjunct, arc *Vertex, id CloseInfo) { if arc.IsDetached() && !arc.anonymous { // Second check necessary ? XXX // If the status is just "conjuncts", we could just take over the arcs. arc.Parent = n.node.Parent + arc.Finalize(n.ctx) for _, a := range arc.Arcs { a.Parent = n.node } diff --git a/internal/core/adt/unify.go b/internal/core/adt/unify.go index 8bd9560b96b..fa90d1f32db 100644 --- a/internal/core/adt/unify.go +++ b/internal/core/adt/unify.go @@ -134,6 +134,15 @@ func (v *Vertex) unify(c *OpContext, needs condition, mode runMode) bool { return false } + // Note that the state of a node can be removed before the node is. + // This happens with the close builtin, for instance. + // See TestFromAPI in pkg export. + // TODO(evalv3): find something more principled. + if v.state == nil && v.cc() != nil && v.cc().conjunctCount == 0 { + v.status = finalized + return true + } + n := v.getState(c) if n == nil { return true // already completed @@ -659,6 +668,10 @@ func (v *Vertex) lookup(c *OpContext, pos token.Pos, f Feature, flags combinedFl } } + // A lookup counts as new structure. See the commend in Section + // "Lookups in inline cycles" in cycle.go. + state.hasNonCycle = true + // TODO: ideally this should not be run at this point. Consider under // which circumstances this is still necessary, and at least ensure // this will not be run if node v currently has a running task.