Skip to content

Commit 9d0e28d

Browse files
mpvlmvdan
authored andcommitted
internal/core/adt: fix default logic
We also need to consider both default modes of the previous pass to work in all conditions. Also renamed the variable names to reflect more closely what is being tracked: we do not track whether there is a default, but rather whether all defaults are eliminated when taking a cross product of a single disjunction. Fixes #3958 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: I8b0b4b59c436a19778a4d1315588e950ae5d1487 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1216865 Reviewed-by: Daniel Martí <[email protected]> TryBot-Result: CUEcueckoo <[email protected]> Unity-Result: CUE porcuepine <[email protected]> Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1217391 Reviewed-by: Roger Peppe <[email protected]>
1 parent fdf8a16 commit 9d0e28d

File tree

2 files changed

+30
-23
lines changed

2 files changed

+30
-23
lines changed

cue/testdata/disjunctions/elimination.txtar

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,12 +1747,12 @@ issue3958: t2: {
17471747
issue3958: (struct){
17481748
t1: (struct){
17491749
#schema: (int){ |((int){ int }, (int){ 3 }, (int){ 1 }) }
1750-
test1: (int){ |(*(int){ 3 }, (int){ int }, (int){ 1 }, (int){ 2 }) }
1751-
test2: (int){ |(*(int){ 3 }, (int){ int }, (int){ 1 }, (int){ 4 }) }
1750+
test1: (int){ |((int){ int }, (int){ 3 }, (int){ 1 }, (int){ 2 }) }
1751+
test2: (int){ |((int){ int }, (int){ 3 }, (int){ 1 }, (int){ 4 }) }
17521752
}
17531753
t2: (struct){
17541754
a: (int){ |((int){ int }, (int){ 8 }, (int){ 3 }, (int){ 1 }, (int){ 4 }) }
1755-
b: (int){ |(*(int){ 3 }, (int){ int }, (int){ 1 }, (int){ 4 }) }
1755+
b: (int){ |((int){ int }, (int){ 3 }, (int){ 1 }, (int){ 4 }) }
17561756
}
17571757
}
17581758
issue770: (struct){
@@ -2631,22 +2631,17 @@ diff old new
26312631
}
26322632
}
26332633
}
2634-
@@ -1204,12 +1085,12 @@
2634+
@@ -1204,8 +1085,8 @@
26352635
issue3958: (struct){
26362636
t1: (struct){
26372637
#schema: (int){ |((int){ int }, (int){ 3 }, (int){ 1 }) }
26382638
- test1: (int){ |((int){ int }, (int){ 2 }, (int){ 3 }, (int){ 1 }) }
26392639
- test2: (int){ |((int){ int }, (int){ 4 }, (int){ 3 }, (int){ 1 }) }
2640-
+ test1: (int){ |(*(int){ 3 }, (int){ int }, (int){ 1 }, (int){ 2 }) }
2641-
+ test2: (int){ |(*(int){ 3 }, (int){ int }, (int){ 1 }, (int){ 4 }) }
2640+
+ test1: (int){ |((int){ int }, (int){ 3 }, (int){ 1 }, (int){ 2 }) }
2641+
+ test2: (int){ |((int){ int }, (int){ 3 }, (int){ 1 }, (int){ 4 }) }
26422642
}
26432643
t2: (struct){
26442644
a: (int){ |((int){ int }, (int){ 8 }, (int){ 3 }, (int){ 1 }, (int){ 4 }) }
2645-
- b: (int){ |((int){ int }, (int){ 3 }, (int){ 1 }, (int){ 4 }) }
2646-
+ b: (int){ |(*(int){ 3 }, (int){ int }, (int){ 1 }, (int){ 4 }) }
2647-
}
2648-
}
2649-
issue770: (struct){
26502645
@@ -1227,10 +1108,10 @@
26512646
v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) }
26522647
}

internal/core/adt/disjunct2.go

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,8 @@ func (n *nodeContext) crossProduct(dst, cross []*nodeContext, dn *envDisjunct, m
383383
// buffer may grow and has a max size of len(cross) * len(dn.disjuncts).
384384
tmp := make([]*nodeContext, 0, len(cross))
385385

386-
leftHasDefault := false
387-
rightHasDefault := false
386+
leftDropsDefault := true
387+
rightDropsDefault := true
388388

389389
for i, p := range cross {
390390
ID := n.nextCrossProduct(i, len(cross), p)
@@ -406,20 +406,21 @@ func (n *nodeContext) crossProduct(dst, cross []*nodeContext, dn *envDisjunct, m
406406
}
407407

408408
tmp = append(tmp, r)
409-
if p.defaultMode == isDefault {
410-
leftHasDefault = true
409+
if p.defaultMode == isDefault || p.origDefaultMode == isDefault {
410+
leftDropsDefault = false
411411
}
412412
if d.mode == isDefault {
413-
rightHasDefault = true
413+
rightDropsDefault = false
414414
}
415415
}
416416
}
417417

418+
hasNonMaybe := false
418419
for _, r := range tmp {
419420
// Unroll nested disjunctions.
420421
switch len(r.disjuncts) {
421422
case 0:
422-
r.defaultMode = combineDefault2(r.defaultMode, r.origDefaultMode, leftHasDefault, rightHasDefault)
423+
r.defaultMode = combineDefault2(r.defaultMode, r.origDefaultMode, leftDropsDefault, rightDropsDefault)
423424
// r did not have a nested disjunction.
424425
dst = appendDisjunct(n.ctx, dst, r)
425426

@@ -430,23 +431,34 @@ func (n *nodeContext) crossProduct(dst, cross []*nodeContext, dn *envDisjunct, m
430431
for _, x := range r.disjuncts {
431432
m := combineDefault(r.origDefaultMode, x.defaultMode)
432433

433-
// TODO(defaults): using rightHasDefault instead of true here is
434-
// not according to the spec, but may result in better user
434+
// TODO(defaults): using rightHasDefault instead of false here
435+
// is not according to the spec, but may result in better user
435436
// ergononmics. See Issue #1304.
436-
x.defaultMode = combineDefault2(r.defaultMode, m, leftHasDefault, true)
437+
x.defaultMode = combineDefault2(r.defaultMode, m, leftDropsDefault, false)
438+
if x.defaultMode != maybeDefault {
439+
hasNonMaybe = true
440+
}
437441
dst = appendDisjunct(n.ctx, dst, x)
438442
}
439443
}
440444
}
441445

446+
if hasNonMaybe {
447+
for _, r := range dst {
448+
if r.defaultMode == maybeDefault {
449+
r.defaultMode = notDefault
450+
}
451+
}
452+
}
453+
442454
return dst
443455
}
444456

445-
func combineDefault2(a, b defaultMode, hasDefaultA, hasDefaultB bool) defaultMode {
446-
if !hasDefaultA {
457+
func combineDefault2(a, b defaultMode, dropsDefaultA, dropsDefaultB bool) defaultMode {
458+
if dropsDefaultA {
447459
a = maybeDefault
448460
}
449-
if !hasDefaultB {
461+
if dropsDefaultB {
450462
b = maybeDefault
451463
}
452464
return combineDefault(a, b)

0 commit comments

Comments
 (0)