Skip to content

Commit f87800d

Browse files
mpvlmvdan
authored andcommitted
internal/core/adt: avoid finalizing too early
unify pro-actively evaluates pending arcs. This pro-active finalization could lead to tasks being forcibly unblocked too early, leaving values to function as "undefined". We now only "require" pending arcs (yield) and do not finalize. Note that if this results in blocks, this will have the same effect as finalization. This does uncover a situation where a value may "yield" oustside of an underlying tasks. In this case, we can simply "fall back" to finalization. Added "related" issue, to show that this change does not break that test. Fixes #3919 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: Ifb6f6374edd9a5a93a43c83bfa002b3b4ee703fc Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1214950 Reviewed-by: Daniel Martí <[email protected]> TryBot-Result: CUEcueckoo <[email protected]> Unity-Result: CUE porcuepine <[email protected]>
1 parent 47c9e99 commit f87800d

File tree

4 files changed

+177
-50
lines changed

4 files changed

+177
-50
lines changed

cue/testdata/eval/comprehensions.txtar

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,9 @@ Result:
271271
// [eval] issue3691.structuralCycle.a.b.c: conflicting values string and {[string]:X} (mismatched types string and struct):
272272
// ./issue3691.cue:14:15
273273
// ./issue3691.cue:15:5
274-
b: (_|_){
275-
// [cycle] cycle error
274+
b*: (_|_){// [e]if true {
275+
// c: 〈3;a〉
276+
// }[e] & 〈1;X〉
276277
}
277278
}
278279
}
@@ -307,18 +308,20 @@ diff old new
307308
// ./issue3691.cue:8:10
308309
}
309310
}
310-
@@ -145,13 +140,8 @@
311+
@@ -145,13 +140,9 @@
311312
// [eval] issue3691.structuralCycle.a.b.c: conflicting values string and {[string]:X} (mismatched types string and struct):
312313
// ./issue3691.cue:14:15
313314
// ./issue3691.cue:15:5
314315
- // ./issue3691.cue:17:3
315316
- // ./issue3691.cue:18:10
316-
b: (_|_){
317+
- b: (_|_){
317318
- // [structural cycle]
318319
- c: (_|_){
319320
- // [structural cycle] issue3691.structuralCycle.a.b.c.b.c: structural cycle
320321
- }
321-
+ // [cycle] cycle error
322+
+ b*: (_|_){// [e]if true {
323+
+ // c: 〈3;a〉
324+
+ // }[e] & 〈1;X〉
322325
}
323326
}
324327
}

cue/testdata/eval/issue3919.txtar

Lines changed: 161 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,63 +19,114 @@ reduced: {
1919
}
2020
port: int | *30080
2121
}
22+
-- secondary.cue --
23+
related: {
24+
[string]: {
25+
if true {
26+
shared: all_total: foo.fooData.total
27+
}
28+
}
29+
foo: fooData: {
30+
total: tags: _hidden
31+
_hidden: extra: {}
32+
}
33+
#Tags: [string]: {}
34+
bar: {
35+
shared: {
36+
[string]: tags: #Tags
37+
bar_total: foo.fooData.total
38+
}
39+
}
40+
}
2241
-- out/eval/stats --
23-
Leaks: 0
24-
Freed: 13
25-
Reused: 5
42+
Leaks: 2
43+
Freed: 32
44+
Reused: 26
2645
Allocs: 8
27-
Retain: 0
46+
Retain: 1
2847

29-
Unifications: 9
30-
Conjuncts: 13
31-
Disjuncts: 13
48+
Unifications: 30
49+
Conjuncts: 51
50+
Disjuncts: 35
3251
-- out/evalalpha --
3352
(struct){
3453
full: (struct){
3554
out: (struct){
3655
env: (struct){
37-
PORT: (_|_){
38-
// [incomplete] full.out.env.PORT: error in call to math.Abs: non-concrete value _:
39-
// ./in.cue:7:11
40-
}
56+
PORT: (int){ 30080 }
4157
}
4258
port: (int){ |(*(int){ 30080 }, (int){ int }) }
4359
}
4460
}
4561
reduced: (struct){
46-
a: (_|_){
47-
// [incomplete] reduced.a: error in call to math.Abs: non-concrete value _:
48-
// ./in.cue:17:6
49-
}
62+
a: (int){ 30080 }
5063
port: (int){ |(*(int){ 30080 }, (int){ int }) }
5164
}
65+
related: (struct){
66+
foo: (struct){
67+
fooData: (struct){
68+
total: (struct){
69+
tags: ~(related.foo.fooData._hidden)
70+
}
71+
_hidden: (struct){
72+
extra: (struct){
73+
}
74+
}
75+
}
76+
shared: (struct){
77+
all_total: ~(related.foo.fooData.total)
78+
}
79+
}
80+
#Tags: (#struct){
81+
}
82+
bar: (struct){
83+
shared: (struct){
84+
bar_total: (struct){
85+
tags: (#struct){
86+
extra: (#struct){
87+
}
88+
}
89+
}
90+
all_total: (struct){
91+
tags: (#struct){
92+
extra: (#struct){
93+
}
94+
}
95+
}
96+
}
97+
}
98+
}
5299
}
53100
-- diff/-out/evalalpha<==>+out/eval --
54101
diff old new
55102
--- old
56103
+++ new
57-
@@ -2,13 +2,19 @@
58-
full: (struct){
59-
out: (struct){
60-
env: (struct){
61-
- PORT: (int){ 30080 }
62-
+ PORT: (_|_){
63-
+ // [incomplete] full.out.env.PORT: error in call to math.Abs: non-concrete value _:
64-
+ // ./in.cue:7:11
65-
+ }
104+
@@ -15,10 +15,7 @@
105+
foo: (struct){
106+
fooData: (struct){
107+
total: (struct){
108+
- tags: (struct){
109+
- extra: (struct){
110+
- }
111+
- }
112+
+ tags: ~(related.foo.fooData._hidden)
113+
}
114+
_hidden: (struct){
115+
extra: (struct){
116+
@@ -26,12 +23,7 @@
117+
}
118+
}
119+
shared: (struct){
120+
- all_total: (struct){
121+
- tags: (struct){
122+
- extra: (struct){
123+
- }
124+
- }
125+
- }
126+
+ all_total: ~(related.foo.fooData.total)
66127
}
67-
port: (int){ |(*(int){ 30080 }, (int){ int }) }
68128
}
69-
}
70-
reduced: (struct){
71-
- a: (int){ 30080 }
72-
+ a: (_|_){
73-
+ // [incomplete] reduced.a: error in call to math.Abs: non-concrete value _:
74-
+ // ./in.cue:17:6
75-
+ }
76-
port: (int){ |(*(int){ 30080 }, (int){ int }) }
77-
}
78-
}
129+
#Tags: (#struct){
79130
-- out/eval --
80131
(struct){
81132
full: (struct){
@@ -90,6 +141,48 @@ diff old new
90141
a: (int){ 30080 }
91142
port: (int){ |(*(int){ 30080 }, (int){ int }) }
92143
}
144+
related: (struct){
145+
foo: (struct){
146+
fooData: (struct){
147+
total: (struct){
148+
tags: (struct){
149+
extra: (struct){
150+
}
151+
}
152+
}
153+
_hidden: (struct){
154+
extra: (struct){
155+
}
156+
}
157+
}
158+
shared: (struct){
159+
all_total: (struct){
160+
tags: (struct){
161+
extra: (struct){
162+
}
163+
}
164+
}
165+
}
166+
}
167+
#Tags: (#struct){
168+
}
169+
bar: (struct){
170+
shared: (struct){
171+
bar_total: (struct){
172+
tags: (#struct){
173+
extra: (#struct){
174+
}
175+
}
176+
}
177+
all_total: (struct){
178+
tags: (#struct){
179+
extra: (#struct){
180+
}
181+
}
182+
}
183+
}
184+
}
185+
}
93186
}
94187
-- out/compile --
95188
--- in.cue
@@ -113,3 +206,36 @@ diff old new
113206
port: (int|*30080)
114207
}
115208
}
209+
--- secondary.cue
210+
{
211+
related: {
212+
[string]: {
213+
if true {
214+
shared: {
215+
all_total: 〈3;foo〉.fooData.total
216+
}
217+
}
218+
}
219+
foo: {
220+
fooData: {
221+
total: {
222+
tags: 〈1;_hidden〉
223+
}
224+
_hidden: {
225+
extra: {}
226+
}
227+
}
228+
}
229+
#Tags: {
230+
[string]: {}
231+
}
232+
bar: {
233+
shared: {
234+
[string]: {
235+
tags: 〈3;#Tags〉
236+
}
237+
bar_total: 〈2;foo〉.fooData.total
238+
}
239+
}
240+
}
241+
}

internal/core/adt/sched.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,9 +413,12 @@ processNextTask:
413413
if s.meets(needs) {
414414
return true
415415
}
416-
c.current().waitFor(s, needs)
417-
s.yield()
418-
panic("unreachable")
416+
// This can happen in some cases. We "promote" to finalization if this
417+
// was not triggered by a task.
418+
if t := c.current(); t != nil {
419+
t.waitFor(s, needs)
420+
s.yield()
421+
}
419422

420423
case finalize:
421424
// remainder of function

internal/core/adt/unify.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,13 +214,8 @@ func (v *Vertex) unify(c *OpContext, needs condition, mode runMode, checkTypos b
214214
if n.node.ArcType == ArcPending {
215215
// forcefully do an early recursive evaluation to decide the state
216216
// of the arc. See https://cuelang.org/issue/3621.
217-
n.process(nodeOnlyNeeds, attemptOnly)
218-
if n.node.ArcType == ArcPending {
219-
for _, a := range n.node.Arcs {
220-
a.unify(c, needs, attemptOnly, checkTypos)
221-
}
222-
}
223-
n.completePending(mode)
217+
n.process(pendingKnown, yield)
218+
n.completePending(yield)
224219
}
225220

226221
n.process(nodeOnlyNeeds, mode)

0 commit comments

Comments
 (0)