Skip to content

Commit d28f285

Browse files
committed
internal/core/adt: impove arcType update logic
This makes closedness checking with arcType updates more robust: - it asserts that "allows" is only called on closeContexts that are done processing - it consolidates recursive logic in a single place instead of sprinkling it throughout comprehension code - it now actively marks disallowed pending nodes as ArcNotPresent - decisions now mostly rely on the arcType in the closeContext only, instead of on both the arc type in the Vertex and closeContext. It also simplifies some of the calling signatures and cleans up some of the logic in the process. Fixes #3533 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: I5f2663fa2167ba2a4bcaadcf9a8f8196c0d3600d Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1203000 Reviewed-by: Daniel Martí <[email protected]> TryBot-Result: CUEcueckoo <[email protected]> Unity-Result: CUE porcuepine <[email protected]>
1 parent 7e82983 commit d28f285

File tree

5 files changed

+67
-163
lines changed

5 files changed

+67
-163
lines changed

cue/testdata/comprehensions/pushdown.txtar

Lines changed: 22 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -803,11 +803,6 @@ embed.fail1.p: field not allowed:
803803
./in.cue:46:7
804804
./in.cue:46:4
805805
./in.cue:49:9
806-
embed.success4.x.y: field not allowed:
807-
./in.cue:76:9
808-
./in.cue:70:7
809-
./in.cue:71:6
810-
./in.cue:76:6
811806
embed.fail4.p: field not allowed:
812807
./in.cue:87:10
813808
./in.cue:87:4
@@ -817,11 +812,6 @@ fieldMismatch.a: cannot combine regular field "x" with 2:
817812
structShare.err1.x.d.e: field not allowed:
818813
./in.cue:591:12
819814
./in.cue:591:9
820-
issue3533.out.metadata.namespace: field not allowed:
821-
./issue3533.cue:7:26
822-
./issue3533.cue:2:15
823-
./issue3533.cue:7:15
824-
./issue3533.cue:11:17
825815

826816
Result:
827817
(_|_){
@@ -890,20 +880,12 @@ Result:
890880
}
891881
#C3: (#struct){
892882
}
893-
success4: (_|_){
894-
// [eval]
883+
success4: (struct){
895884
#X: (#struct){
896885
y: (string){ string }
897886
}
898-
x: (_|_){
899-
// [eval]
900-
y: (_|_){
901-
// [eval] embed.success4.x.y: field not allowed:
902-
// ./in.cue:76:9
903-
// ./in.cue:70:7
904-
// ./in.cue:71:6
905-
// ./in.cue:76:6
906-
}
887+
x: (#struct){
888+
y: (string){ string }
907889
}
908890
}
909891
fail4: (_|_){
@@ -1432,22 +1414,13 @@ Result:
14321414
root: (#struct){
14331415
}
14341416
}
1435-
issue3533: (_|_){
1436-
// [eval]
1417+
issue3533: (struct){
14371418
#ObjectMeta: (#struct){
14381419
namespace?: (string){ string }
14391420
}
1440-
out: (_|_){
1441-
// [eval]
1442-
metadata: (_|_){
1443-
// [eval]
1444-
namespace: (_|_){
1445-
// [eval] issue3533.out.metadata.namespace: field not allowed:
1446-
// ./issue3533.cue:7:26
1447-
// ./issue3533.cue:2:15
1448-
// ./issue3533.cue:7:15
1449-
// ./issue3533.cue:11:17
1450-
}
1421+
out: (struct){
1422+
metadata: (#struct){
1423+
namespace: (string){ |(*(string){ "default" }, (string){ string }) }
14511424
}
14521425
}
14531426
}
@@ -1475,7 +1448,7 @@ Result:
14751448
diff old new
14761449
--- old
14771450
+++ new
1478-
@@ -1,32 +1,29 @@
1451+
@@ -1,32 +1,19 @@
14791452
Errors:
14801453
+noStackOverflowStructCycle.#list.tail: structural cycle
14811454
+noStackOverflowStructCycle.list.tail: structural cycle
@@ -1487,11 +1460,6 @@ diff old new
14871460
+ ./in.cue:46:7
14881461
./in.cue:46:4
14891462
./in.cue:49:9
1490-
+embed.success4.x.y: field not allowed:
1491-
+ ./in.cue:76:9
1492-
+ ./in.cue:70:7
1493-
+ ./in.cue:71:6
1494-
+ ./in.cue:76:6
14951463
embed.fail4.p: field not allowed:
14961464
- ./in.cue:82:9
14971465
- ./in.cue:83:7
@@ -1517,15 +1485,10 @@ diff old new
15171485
+structShare.err1.x.d.e: field not allowed:
15181486
+ ./in.cue:591:12
15191487
+ ./in.cue:591:9
1520-
+issue3533.out.metadata.namespace: field not allowed:
1521-
+ ./issue3533.cue:7:26
1522-
+ ./issue3533.cue:2:15
1523-
+ ./issue3533.cue:7:15
1524-
+ ./issue3533.cue:11:17
15251488

15261489
Result:
15271490
(_|_){
1528-
@@ -68,8 +65,8 @@
1491+
@@ -68,8 +55,8 @@
15291492
}
15301493
fail: (struct){
15311494
a: (_|_){
@@ -1536,7 +1499,7 @@ diff old new
15361499
}
15371500
}
15381501
embed: (_|_){
1539-
@@ -78,10 +75,7 @@
1502+
@@ -78,10 +65,7 @@
15401503
// [eval]
15411504
p: (_|_){
15421505
// [eval] embed.fail1.p: field not allowed:
@@ -1548,31 +1511,7 @@ diff old new
15481511
// ./in.cue:46:4
15491512
// ./in.cue:49:9
15501513
}
1551-
@@ -98,12 +92,20 @@
1552-
}
1553-
#C3: (#struct){
1554-
}
1555-
- success4: (struct){
1556-
+ success4: (_|_){
1557-
+ // [eval]
1558-
#X: (#struct){
1559-
y: (string){ string }
1560-
}
1561-
- x: (#struct){
1562-
- y: (string){ string }
1563-
+ x: (_|_){
1564-
+ // [eval]
1565-
+ y: (_|_){
1566-
+ // [eval] embed.success4.x.y: field not allowed:
1567-
+ // ./in.cue:76:9
1568-
+ // ./in.cue:70:7
1569-
+ // ./in.cue:71:6
1570-
+ // ./in.cue:76:6
1571-
+ }
1572-
}
1573-
}
1574-
fail4: (_|_){
1575-
@@ -110,10 +112,7 @@
1514+
@@ -110,10 +94,7 @@
15761515
// [eval]
15771516
p: (_|_){
15781517
// [eval] embed.fail4.p: field not allowed:
@@ -1584,7 +1523,7 @@ diff old new
15841523
// ./in.cue:87:4
15851524
q: (int){ 1 }
15861525
}
1587-
@@ -187,8 +186,7 @@
1526+
@@ -187,8 +168,7 @@
15881527
// [structural cycle] noStackOverflowStructCycle.list.tail: structural cycle
15891528
}
15901529
}
@@ -1594,7 +1533,7 @@ diff old new
15941533
t1: (struct){
15951534
#a: (_|_){
15961535
// [incomplete] provideIncompleteSuccess.t1.#a: incomplete bool: bool:
1597-
@@ -196,16 +194,12 @@
1536+
@@ -196,16 +176,12 @@
15981537
b: (bool){ bool }
15991538
}
16001539
x: (#struct){
@@ -1617,7 +1556,7 @@ diff old new
16171556
#a: (#struct){
16181557
c: (int){ 4 }
16191558
b: (bool){ true }
1620-
@@ -212,17 +206,8 @@
1559+
@@ -212,17 +188,8 @@
16211560
}
16221561
#c: (#struct){
16231562
}
@@ -1637,7 +1576,7 @@ diff old new
16371576
}
16381577
b: (bool){ true }
16391578
}
1640-
@@ -252,9 +237,22 @@
1579+
@@ -252,9 +219,22 @@
16411580
}
16421581
cyclicError: (struct){
16431582
a: (_|_){
@@ -1663,7 +1602,7 @@ diff old new
16631602
}
16641603
}
16651604
midwayReferences: (struct){
1666-
@@ -268,24 +266,9 @@
1605+
@@ -268,24 +248,9 @@
16671606
}
16681607
}
16691608
}
@@ -1691,7 +1630,7 @@ diff old new
16911630
}
16921631
closedCheck: (struct){
16931632
success1: (struct){
1694-
@@ -388,13 +371,7 @@
1633+
@@ -388,13 +353,7 @@
16951634
}
16961635
}
16971636
}
@@ -1706,7 +1645,7 @@ diff old new
17061645
#F: (#struct){
17071646
e: (bool){ bool }
17081647
f: (_|_){
1709-
@@ -411,17 +388,10 @@
1648+
@@ -411,17 +370,10 @@
17101649
}
17111650
}
17121651
E: (_|_){
@@ -1725,7 +1664,7 @@ diff old new
17251664
}
17261665
}
17271666
derefDisj2: (struct){
1728-
@@ -432,17 +402,10 @@
1667+
@@ -432,17 +384,10 @@
17291668
}
17301669
}
17311670
E: (_|_){
@@ -1744,7 +1683,7 @@ diff old new
17441683
}
17451684
}
17461685
bulk1: (struct){
1747-
@@ -565,9 +528,7 @@
1686+
@@ -565,9 +510,7 @@
17481687
// [eval]
17491688
e: (_|_){
17501689
// [eval] structShare.err1.x.d.e: field not allowed:
@@ -1755,7 +1694,7 @@ diff old new
17551694
// ./in.cue:591:9
17561695
}
17571696
}
1758-
@@ -591,13 +552,13 @@
1697+
@@ -591,13 +534,13 @@
17591698
}
17601699
envs: (struct){
17611700
e1: (#struct){
@@ -1773,7 +1712,7 @@ diff old new
17731712
}
17741713
}
17751714
}
1776-
@@ -634,9 +595,8 @@
1715+
@@ -634,9 +577,8 @@
17771716
_c: (struct){
17781717
y: (int){ 1 }
17791718
}
@@ -1785,33 +1724,6 @@ diff old new
17851724
}
17861725
}
17871726
errorPropagation: (_|_){
1788-
@@ -674,13 +634,22 @@
1789-
root: (#struct){
1790-
}
1791-
}
1792-
- issue3533: (struct){
1793-
+ issue3533: (_|_){
1794-
+ // [eval]
1795-
#ObjectMeta: (#struct){
1796-
namespace?: (string){ string }
1797-
}
1798-
- out: (struct){
1799-
- metadata: (#struct){
1800-
- namespace: (string){ |(*(string){ "default" }, (string){ string }) }
1801-
+ out: (_|_){
1802-
+ // [eval]
1803-
+ metadata: (_|_){
1804-
+ // [eval]
1805-
+ namespace: (_|_){
1806-
+ // [eval] issue3533.out.metadata.namespace: field not allowed:
1807-
+ // ./issue3533.cue:7:26
1808-
+ // ./issue3533.cue:2:15
1809-
+ // ./issue3533.cue:7:15
1810-
+ // ./issue3533.cue:11:17
1811-
+ }
1812-
}
1813-
}
1814-
}
18151727
-- diff/-out/evalalpha/stats<==>+out/eval/stats --
18161728
diff old new
18171729
--- old

cue/testdata/cycle/issue990.txtar

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Allocs: 1392
9090
Retain: 0
9191

9292
Unifications: 183
93-
Conjuncts: 4545
93+
Conjuncts: 4543
9494
Disjuncts: 284
9595
-- out/evalalpha --
9696
Errors:
@@ -268,7 +268,7 @@ diff old new
268268
-Conjuncts: 12017
269269
-Disjuncts: 3244
270270
+Unifications: 183
271-
+Conjuncts: 4545
271+
+Conjuncts: 4543
272272
+Disjuncts: 284
273273
-- diff/-out/evalalpha<==>+out/eval --
274274
diff old new

internal/core/adt/comprehension.go

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -463,30 +463,20 @@ func (n *nodeContext) processComprehensionInner(d *envYield, state vertexStatus)
463463
d.inserted = true
464464

465465
if len(d.envs) == 0 {
466-
c := d.leaf
467-
for p := c.arcCC; p != nil; p = p.parent {
468-
// because the parent referrer will reach a zero count before this
469-
// node will reach a zero count, we need to propagate the arcType.
470-
p.updateArcType(ArcNotPresent)
471-
}
466+
c := d.leaf.arcCC
467+
// because the parent referrer will reach a zero count before this
468+
// node will reach a zero count, we need to propagate the arcType.
469+
c.updateArcType(ctx, ArcNotPresent)
472470
return nil
473471
}
474472

475473
v := n.node
476-
f := v.Label
477474
for c := d.leaf; c.parent != nil; c = c.parent {
478475
// because the parent referrer will reach a zero count before this
479476
// node will reach a zero count, we need to propagate the arcType.
480-
for arc, p := c.arcCC, c.cc; p != nil; arc, p = arc.parent, p.parent {
481-
482-
t := arc.arcType
483-
if p.isClosed && t >= ArcPending && !p.allows(ctx, f, arc) {
484-
ctx.notAllowedError(p.src, arc.src)
485-
}
486-
// TODO: remove this line once we use the arcType of the
487-
// closeContext in notAllowedError.
488-
arc.src.updateArcType(c.arcType)
489-
arc.updateArcType(c.arcType)
477+
if p := c.arcCC; p != nil {
478+
p.src.updateArcType(c.arcType)
479+
p.updateArcType(ctx, c.arcType)
490480
}
491481
v.updateArcType(c.arcType)
492482
if v.ArcType == ArcNotPresent {

internal/core/adt/conjunct.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,14 @@ loop2:
278278
case *Comprehension, Expr:
279279
// No need to increment and decrement, as there will be at least
280280
// one entry.
281-
if _, ok := s.Src.(*ast.File); !ok {
281+
if _, ok := s.Src.(*ast.File); !ok && s.Src != nil {
282282
// If this is not a file, the struct indicates the scope/
283283
// boundary at which closedness should apply. This is not true
284284
// for files.
285+
// We should also not spawn if this is a nested Comprehension,
286+
// where the spawn is already done as it may lead to spurious
287+
// field not allowed errors. We can detect this with a nil s.Src.
288+
// TODO(evalv3): use a more principled detection mechanism.
285289
// TODO: set this as a flag in StructLit so as to not have to
286290
// do the somewhat dangerous cast here.
287291
ci, _ = ci.spawnCloseContext(n.ctx, 0)

0 commit comments

Comments
 (0)