Skip to content

Commit 7dd29f1

Browse files
committed
internal/core/adt: delay dereferencing in lookup
This fixes a bug in the API, where dereferencing caused Value.Dereference to be too eager. This changes test in elimination.txtar. The results are a bit better, but still wrong, so it seems. So no changes in the todos. The main change is that Vertex.lookup no longer fully dereferences. Dereferencing is now done in a bespoke manner at the call sites of lookup. Issue #3060 Issue #2884 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: I59f791e78213c3cdacdb8ad3b6ba829a73d2d6ca Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1194104 Reviewed-by: Daniel Martí <[email protected]> TryBot-Result: CUEcueckoo <[email protected]> Unity-Result: CUE porcuepine <[email protected]>
1 parent 8935df9 commit 7dd29f1

File tree

9 files changed

+135
-82
lines changed

9 files changed

+135
-82
lines changed

cue/testdata/cycle/chain.txtar

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -208,21 +208,21 @@ issue2052: full: {
208208
d: #Depth & {#in: tree}
209209
}
210210
-- out/evalalpha/stats --
211-
Leaks: 22127
212-
Freed: 1994
213-
Reused: 1993
214-
Allocs: 22128
211+
Leaks: 19985
212+
Freed: 1462
213+
Reused: 1461
214+
Allocs: 19986
215215
Retain: 0
216216

217-
Unifications: 8358
218-
Conjuncts: 121910
219-
Disjuncts: 15463
217+
Unifications: 7496
218+
Conjuncts: 107561
219+
Disjuncts: 13651
220220
-- out/evalalpha --
221221
Errors:
222222
issue2052.t1.#Depth: adding field #basic not allowed as field set was already referenced:
223223
./issue2052.cue:8:20
224224
issue2052.t2.#Depth: adding field #basic not allowed as field set was already referenced:
225-
./issue2052.cue:46:14
225+
./issue2052.cue:41:20
226226

227227
Result:
228228
(_|_){
@@ -350,7 +350,7 @@ Result:
350350
// [eval]
351351
#Depth: (_|_){
352352
// [eval] issue2052.t2.#Depth: adding field #basic not allowed as field set was already referenced:
353-
// ./issue2052.cue:46:14
353+
// ./issue2052.cue:41:20
354354
#maxiter: (int){ 4 }
355355
#funcs: (#struct){
356356
"4": (null){ null }
@@ -725,18 +725,18 @@ diff old new
725725
-Reused: 1801
726726
-Allocs: 84
727727
-Retain: 185
728-
+Leaks: 22127
729-
+Freed: 1994
730-
+Reused: 1993
731-
+Allocs: 22128
728+
+Leaks: 19985
729+
+Freed: 1462
730+
+Reused: 1461
731+
+Allocs: 19986
732732
+Retain: 0
733733

734734
-Unifications: 800
735735
-Conjuncts: 3175
736736
-Disjuncts: 1974
737-
+Unifications: 8358
738-
+Conjuncts: 121910
739-
+Disjuncts: 15463
737+
+Unifications: 7496
738+
+Conjuncts: 107561
739+
+Disjuncts: 13651
740740
-- diff/-out/evalalpha<==>+out/eval --
741741
diff old new
742742
--- old
@@ -747,7 +747,7 @@ diff old new
747747
+issue2052.t1.#Depth: adding field #basic not allowed as field set was already referenced:
748748
+ ./issue2052.cue:8:20
749749
+issue2052.t2.#Depth: adding field #basic not allowed as field set was already referenced:
750-
+ ./issue2052.cue:46:14
750+
+ ./issue2052.cue:41:20
751751
+
752752
+Result:
753753
+(_|_){
@@ -969,7 +969,7 @@ diff old new
969969
+ // [eval]
970970
+ #Depth: (_|_){
971971
+ // [eval] issue2052.t2.#Depth: adding field #basic not allowed as field set was already referenced:
972-
+ // ./issue2052.cue:46:14
972+
+ // ./issue2052.cue:41:20
973973
+ #maxiter: (int){ 4 }
974974
+ #funcs: (#struct){
975975
+ "4": (null){ null }

cue/testdata/cycle/comprehension.txtar

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -310,15 +310,15 @@ issue2367: {
310310
}
311311

312312
-- out/evalalpha/stats --
313-
Leaks: 451
313+
Leaks: 431
314314
Freed: 12
315315
Reused: 12
316-
Allocs: 451
316+
Allocs: 431
317317
Retain: 0
318318

319-
Unifications: 375
320-
Conjuncts: 2094
321-
Disjuncts: 58
319+
Unifications: 397
320+
Conjuncts: 2202
321+
Disjuncts: 36
322322
-- out/evalalpha --
323323
Errors:
324324
issue1881.p1.o.retry: field not allowed:
@@ -1482,18 +1482,18 @@ diff old new
14821482
-Reused: 1260
14831483
-Allocs: 60
14841484
-Retain: 145
1485-
+Leaks: 451
1485+
+Leaks: 431
14861486
+Freed: 12
14871487
+Reused: 12
1488-
+Allocs: 451
1488+
+Allocs: 431
14891489
+Retain: 0
14901490

14911491
-Unifications: 832
14921492
-Conjuncts: 2525
14931493
-Disjuncts: 1404
1494-
+Unifications: 375
1495-
+Conjuncts: 2094
1496-
+Disjuncts: 58
1494+
+Unifications: 397
1495+
+Conjuncts: 2202
1496+
+Disjuncts: 36
14971497
-- out/eval/stats --
14981498
Leaks: 50
14991499
Freed: 1270

cue/testdata/disjunctions/elimination.txtar

Lines changed: 79 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -979,22 +979,37 @@ issue2263: full: {
979979
}
980980
BAZ: (_){ _ }
981981
}
982-
t3: (struct){
983-
#A: (#struct){
984-
v: (int){ 1 }
985-
}
986-
BAZ: (_){ _ }
987-
S: (#struct){
988-
x: (int){ 1 }
989-
y: (int){ 1 }
990-
}
991-
#B: (#struct){
992-
x: (int){ 1 }
993-
y: (int){ 1 }
994-
}
995-
f1: (int){ int }
996-
f2: (int){ int }
997-
}
982+
t3: (struct){ |((struct){
983+
#A: (#struct){
984+
v: (int){ 1 }
985+
}
986+
BAZ: (_){ _ }
987+
S: (#struct){
988+
x: (int){ 1 }
989+
y: (int){ 1 }
990+
}
991+
#B: (#struct){
992+
x: (int){ 1 }
993+
y: (int){ 1 }
994+
}
995+
f1: (int){ int }
996+
f2: (int){ int }
997+
}, (struct){
998+
#A: (#struct){
999+
v: (int){ 1 }
1000+
}
1001+
BAZ: (_){ _ }
1002+
S: (#struct){
1003+
x: (int){ 1 }
1004+
y: (int){ 1 }
1005+
}
1006+
#B: (#struct){
1007+
x: (int){ 1 }
1008+
y: (int){ 1 }
1009+
}
1010+
f1: (int){ int }
1011+
b2: (int){ int }
1012+
}) }
9981013
}
9991014
full: (struct){
10001015
Foo: (#struct){
@@ -1646,7 +1661,7 @@ diff old new
16461661
t1: (struct){
16471662
#SpecFoo: (#struct){
16481663
foo: (#struct){
1649-
@@ -508,185 +484,103 @@
1664+
@@ -508,185 +484,118 @@
16501665
x: (int){ 1 }
16511666
}
16521667
}
@@ -1669,16 +1684,9 @@ diff old new
16691684
- t3: (_|_){
16701685
- // [eval] issue2209.simplified.t3.BAZ: undefined field: y:
16711686
- // ./issue2209full.cue:35:9
1672-
+ spec: (struct){
1673-
+ bar: (struct){
1674-
+ }
1675-
+ }
1676-
+ BAZ: (_){ _ }
1677-
+ }
1678-
+ t3: (struct){
1679-
#A: (#struct){
1680-
v: (int){ 1 }
1681-
}
1687+
- #A: (#struct){
1688+
- v: (int){ 1 }
1689+
- }
16821690
- BAZ: (_|_){
16831691
- // [eval] issue2209.simplified.t3.BAZ: undefined field: y:
16841692
- // ./issue2209full.cue:35:9
@@ -1690,23 +1698,52 @@ diff old new
16901698
- x: (int){ 1 }
16911699
- y: (int){ 1 }
16921700
- }) }
1693-
+ BAZ: (_){ _ }
1694-
+ S: (#struct){
1695-
+ x: (int){ 1 }
1696-
+ y: (int){ 1 }
1697-
+ }
1698-
#B: (#struct){
1699-
x: (int){ 1 }
1700-
y: (int){ 1 }
1701-
}
1701+
- #B: (#struct){
1702+
- x: (int){ 1 }
1703+
- y: (int){ 1 }
1704+
- }
17021705
- b2: (int){ int }
17031706
- }
17041707
- }
17051708
- full: (_|_){
17061709
- // [eval]
1707-
+ f1: (int){ int }
1708-
+ f2: (int){ int }
1710+
+ spec: (struct){
1711+
+ bar: (struct){
1712+
+ }
1713+
+ }
1714+
+ BAZ: (_){ _ }
17091715
+ }
1716+
+ t3: (struct){ |((struct){
1717+
+ #A: (#struct){
1718+
+ v: (int){ 1 }
1719+
+ }
1720+
+ BAZ: (_){ _ }
1721+
+ S: (#struct){
1722+
+ x: (int){ 1 }
1723+
+ y: (int){ 1 }
1724+
+ }
1725+
+ #B: (#struct){
1726+
+ x: (int){ 1 }
1727+
+ y: (int){ 1 }
1728+
+ }
1729+
+ f1: (int){ int }
1730+
+ f2: (int){ int }
1731+
+ }, (struct){
1732+
+ #A: (#struct){
1733+
+ v: (int){ 1 }
1734+
+ }
1735+
+ BAZ: (_){ _ }
1736+
+ S: (#struct){
1737+
+ x: (int){ 1 }
1738+
+ y: (int){ 1 }
1739+
+ }
1740+
+ #B: (#struct){
1741+
+ x: (int){ 1 }
1742+
+ y: (int){ 1 }
1743+
+ }
1744+
+ f1: (int){ int }
1745+
+ b2: (int){ int }
1746+
+ }) }
17101747
+ }
17111748
+ full: (struct){
17121749
Foo: (#struct){
@@ -1921,7 +1958,7 @@ diff old new
19211958
}
19221959
}
19231960
#Abstract: (#struct){
1924-
@@ -702,34 +596,34 @@
1961+
@@ -702,34 +611,34 @@
19251962
}
19261963
}) }
19271964
resource: (#struct){
@@ -1984,7 +2021,7 @@ diff old new
19842021
}
19852022
}
19862023
_#Spec: (#struct){ |(*(#struct){
1987-
@@ -756,36 +650,36 @@
2024+
@@ -756,36 +665,36 @@
19882025
}
19892026
}
19902027
_Thing: (#struct){
@@ -2050,7 +2087,7 @@ diff old new
20502087
}
20512088
#Constrained: (#struct){
20522089
spec: (#struct){ |(*(#struct){
2053-
@@ -869,19 +763,19 @@
2090+
@@ -869,19 +778,19 @@
20542091
common: (int){ 3 }
20552092
}
20562093
#FormFoo: (#struct){
@@ -2077,7 +2114,7 @@ diff old new
20772114
}) }
20782115
}
20792116
#Input: (#struct){
2080-
@@ -930,10 +824,23 @@
2117+
@@ -930,10 +839,23 @@
20812118
}
20822119
full: (struct){
20832120
metrics: (#list){

cue/types.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,6 @@ func (i *Iterator) Next() bool {
235235
p := linkParent(i.val.parent_, i.val.v, arc)
236236
i.f = arc.Label
237237
i.arcType = arc.ArcType
238-
// TODO(deref): this should not indirect disjunctions, as this will cause losing
239-
// information, which is now available in the new evaluator. Find a safe
240-
// way to preserve disjunction information while keeping backward
241-
// compatibility in the API.
242-
arc = arc.DerefValue()
243238
i.cur = makeValue(i.val.idx, arc, p)
244239
i.p++
245240
return true

cue/types_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3559,8 +3559,6 @@ func TestPathCorrection(t *testing.T) {
35593559
continue
35603560
}
35613561
runMatrix(t, "", func(t *testing.T, cfg *evalConfig) {
3562-
TODO_Sharing(t, cfg)
3563-
35643562
r := cfg.runtime()
35653563

35663564
inst, err := r.Compile("in", tc.input)

internal/core/adt/context.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,10 @@ func (c *OpContext) evalState(v Expr, state combinedFlags) (result Value) {
710710
if arc == nil {
711711
return nil
712712
}
713+
// TODO(deref): what is the right level of dereferencing here?
714+
// DerefValue seems to work too.
715+
arc = arc.DerefNonShared()
716+
713717
// TODO: consider moving this after markCycle, depending on how we
714718
// implement markCycle, or whether we need it at all.
715719
// TODO: is this indirect necessary?
@@ -838,6 +842,8 @@ func (c *OpContext) unifyNode(v Expr, state combinedFlags) (result Value) {
838842
if v == nil {
839843
return nil
840844
}
845+
v = v.DerefValue()
846+
841847
// TODO: consider moving this after markCycle, depending on how we
842848
// implement markCycle, or whether we need it at all.
843849
// TODO: is this indirect necessary?

internal/core/adt/share.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,17 @@ func (v *Vertex) DerefNonDisjunct() *Vertex {
153153
}
154154
}
155155

156+
// DerefNonRooted indirects a node that points to a value that is not rooted.
157+
func (v *Vertex) DerefNonRooted() *Vertex {
158+
for {
159+
arc, ok := v.BaseValue.(*Vertex)
160+
if !ok || arc.IsDisjunct || v.IsShared {
161+
return v
162+
}
163+
v = arc
164+
}
165+
}
166+
156167
// DerefNonShared finds the indirection of an arc that is not the result of
157168
// structure sharing. This is especially relevant when indirecting disjunction
158169
// values.

internal/core/adt/tasks.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ func processResolver(ctx *OpContext, t *task, mode runMode) {
101101
// TODO: yield instead?
102102
return
103103
}
104+
arc = arc.DerefNonDisjunct()
105+
104106
ctx.Logf(t.node.node, "RESOLVED %v to %v %v", r, arc.Label, fmt.Sprintf("%p", arc))
105107
// TODO: consider moving after markCycle or removing.
106108
d := arc.DerefDisjunct()

0 commit comments

Comments
 (0)