Skip to content

Commit 9e85cd7

Browse files
committed
internal/core/adt: fix validator closedness issue
A validator has type _. The code responsible for handling validators explicitly set this type in a closeContext. However, it did so after deduplicating the validator. This would cause identical validators defined in a definition that were added through a different closeContext to effectively be typed as an empty struct. The fix is to just unconditionally set top in the closeContext. Note that this CL also removes a duplicate and redundant updateNodeType Fixes #3661 Fixes #3639 Fixes #3678 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: I6a8df82e58425b068893744eaefeca4710e6a8a1 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1207237 TryBot-Result: CUEcueckoo <[email protected]> Reviewed-by: Daniel Martí <[email protected]> Unity-Result: CUE porcuepine <[email protected]>
1 parent d0564de commit 9e85cd7

File tree

2 files changed

+40
-125
lines changed

2 files changed

+40
-125
lines changed

cue/testdata/builtins/validators.txtar

+32-118
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,6 @@ Conjuncts: 327
223223
Disjuncts: 202
224224
-- out/evalalpha --
225225
Errors:
226-
issue3639.a.b: field not allowed:
227-
./validator_is_top.cue:3:5
228226
callOfCallToValidator.e: cannot call previously called validator b:
229227
./in.cue:94:5
230228
issue3418.t1: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1:
@@ -270,12 +268,6 @@ issue3474.topValidator.failType.A: invalid value {C:1} (does not satisfy matchN)
270268
./issue3474.cue:53:5
271269
./issue3474.cue:53:12
272270
./issue3474.cue:54:5
273-
issue3661.a.b: field not allowed:
274-
./validator_is_top.cue:7:6
275-
./validator_is_top.cue:8:5
276-
issue3678.y.c: field not allowed:
277-
./validator_is_top.cue:13:6
278-
./validator_is_top.cue:19:5
279271

280272
Result:
281273
(_|_){
@@ -489,15 +481,9 @@ Result:
489481
}
490482
}
491483
}
492-
issue3639: (_|_){
493-
// [eval]
494-
a: (_|_){
495-
// [eval] issue3639.a.b: field not allowed:
496-
// ./validator_is_top.cue:3:5
497-
b: (_|_){
498-
// [eval] issue3639.a.b: field not allowed:
499-
// ./validator_is_top.cue:3:5
500-
}
484+
issue3639: (struct){
485+
a: (#struct){
486+
b: (int){ 1 }
501487
}
502488
#X: (_){ matchN(1, (#list){
503489
0: (_|_){// &[{
@@ -506,27 +492,18 @@ Result:
506492
}
507493
}) }
508494
}
509-
issue3661: (_|_){
510-
// [eval]
495+
issue3661: (struct){
511496
#X: (_){ matchN(1, (#list){
512497
0: (_|_){// &[{
513498
// b!: int
514499
// }]
515500
}
516501
}) }
517-
a: (_|_){
518-
// [eval] issue3661.a.b: field not allowed:
519-
// ./validator_is_top.cue:7:6
520-
// ./validator_is_top.cue:8:5
521-
b: (_|_){
522-
// [eval] issue3661.a.b: field not allowed:
523-
// ./validator_is_top.cue:7:6
524-
// ./validator_is_top.cue:8:5
525-
}
502+
a: (#struct){
503+
b: (int){ 1 }
526504
}
527505
}
528-
issue3678: (_|_){
529-
// [eval]
506+
issue3678: (struct){
530507
#X: (_){ matchN(1, (#list){
531508
0: (_|_){// &[{
532509
// a!: string
@@ -540,30 +517,16 @@ Result:
540517
x: (#struct){
541518
c: (string){ "c" }
542519
}
543-
y: (_|_){
544-
// [eval] issue3678.y.c: field not allowed:
545-
// ./validator_is_top.cue:13:6
546-
// ./validator_is_top.cue:19:5
547-
c: (_|_){
548-
// [eval] issue3678.y.c: field not allowed:
549-
// ./validator_is_top.cue:13:6
550-
// ./validator_is_top.cue:19:5
551-
}
520+
y: (#struct){
521+
c: (string){ "c" }
552522
}
553523
}
554524
}
555525
-- diff/-out/evalalpha<==>+out/eval --
556526
diff old new
557527
--- old
558528
+++ new
559-
@@ -1,4 +1,6 @@
560-
Errors:
561-
+issue3639.a.b: field not allowed:
562-
+ ./validator_is_top.cue:3:5
563-
callOfCallToValidator.e: cannot call previously called validator b:
564-
./in.cue:94:5
565-
issue3418.t1: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1:
566-
@@ -27,7 +29,7 @@
529+
@@ -27,7 +27,7 @@
567530
./issue3418.cue:10:16
568531
./issue3418.cue:10:18
569532
./issue3418.cue:11:5
@@ -572,20 +535,7 @@ diff old new
572535
./issue3474.cue:12:5
573536
./issue3474.cue:12:22
574537
./issue3474.cue:13:5
575-
@@ -44,6 +46,12 @@
576-
./issue3474.cue:53:5
577-
./issue3474.cue:53:12
578-
./issue3474.cue:54:5
579-
+issue3661.a.b: field not allowed:
580-
+ ./validator_is_top.cue:7:6
581-
+ ./validator_is_top.cue:8:5
582-
+issue3678.y.c: field not allowed:
583-
+ ./validator_is_top.cue:13:6
584-
+ ./validator_is_top.cue:19:5
585-
586-
Result:
587-
(_|_){
588-
@@ -134,11 +142,7 @@
538+
@@ -134,11 +134,7 @@
589539
0: (int){ 1 }
590540
}
591541
}
@@ -598,7 +548,7 @@ diff old new
598548
_a: (_|_){
599549
// [incomplete] issue2098.incomplete1._a: invalid value [] (does not satisfy list.MinItems(1)): len(list) < MinItems(1) (0 < 1):
600550
// ./in.cue:112:6
601-
@@ -202,7 +206,7 @@
551+
@@ -202,7 +198,7 @@
602552
failAfter: (_|_){
603553
// [eval]
604554
A: (_|_){
@@ -607,7 +557,7 @@ diff old new
607557
// ./issue3474.cue:12:5
608558
// ./issue3474.cue:12:22
609559
// ./issue3474.cue:13:5
610-
@@ -245,7 +249,7 @@
560+
@@ -245,7 +241,7 @@
611561
}
612562
incomplete: (struct){
613563
A: (int){ &(matchN(1, (#list){
@@ -616,72 +566,45 @@ diff old new
616566
}
617567
}), int) }
618568
}
619-
@@ -261,44 +265,66 @@
620-
}
569+
@@ -262,42 +258,42 @@
621570
}
622571
}
623-
- issue3639: (struct){
572+
issue3639: (struct){
624573
- a: (struct){
625574
- b: (int){ 1 }
626575
- }
627576
- #X: (_){ matchN(1, (#list){
628577
- 0: (_|_){// {
629-
+ issue3639: (_|_){
630-
+ // [eval]
631-
+ a: (_|_){
632-
+ // [eval] issue3639.a.b: field not allowed:
633-
+ // ./validator_is_top.cue:3:5
634-
+ b: (_|_){
635-
+ // [eval] issue3639.a.b: field not allowed:
636-
+ // ./validator_is_top.cue:3:5
637-
+ }
578+
+ a: (#struct){
579+
+ b: (int){ 1 }
638580
+ }
639581
+ #X: (_){ matchN(1, (#list){
640582
+ 0: (_|_){// &[{
641583
// b: int
642584
- // }
643-
- }
644-
- }) }
645-
- }
646-
- issue3661: (struct){
647-
- #X: (_){ matchN(1, (#list){
648-
- 0: (_|_){// {
649585
+ // }]
650-
+ }
651-
+ }) }
652-
+ }
653-
+ issue3661: (_|_){
654-
+ // [eval]
655-
+ #X: (_){ matchN(1, (#list){
586+
}
587+
}) }
588+
}
589+
issue3661: (struct){
590+
#X: (_){ matchN(1, (#list){
591+
- 0: (_|_){// {
656592
+ 0: (_|_){// &[{
657593
// b!: int
658594
- // }
659595
- }
660596
- }) }
661597
- a: (struct){
662-
- b: (int){ 1 }
663-
- }
664-
- }
665-
- issue3678: (struct){
666-
- #X: (_){ matchN(1, (#list){
667-
- 0: (_|_){// {
668598
+ // }]
669599
+ }
670600
+ }) }
671-
+ a: (_|_){
672-
+ // [eval] issue3661.a.b: field not allowed:
673-
+ // ./validator_is_top.cue:7:6
674-
+ // ./validator_is_top.cue:8:5
675-
+ b: (_|_){
676-
+ // [eval] issue3661.a.b: field not allowed:
677-
+ // ./validator_is_top.cue:7:6
678-
+ // ./validator_is_top.cue:8:5
679-
+ }
680-
+ }
681-
+ }
682-
+ issue3678: (_|_){
683-
+ // [eval]
684-
+ #X: (_){ matchN(1, (#list){
601+
+ a: (#struct){
602+
b: (int){ 1 }
603+
}
604+
}
605+
issue3678: (struct){
606+
#X: (_){ matchN(1, (#list){
607+
- 0: (_|_){// {
685608
+ 0: (_|_){// &[{
686609
// a!: string
687610
- // }
@@ -698,25 +621,16 @@ diff old new
698621
- c: (string){ "c" }
699622
- }
700623
- y: (struct){
701-
- c: (string){ "c" }
702624
+ // }]
703625
+ }
704626
+ }) }
705627
+ x: (#struct){
706628
+ c: (string){ "c" }
707629
+ }
708-
+ y: (_|_){
709-
+ // [eval] issue3678.y.c: field not allowed:
710-
+ // ./validator_is_top.cue:13:6
711-
+ // ./validator_is_top.cue:19:5
712-
+ c: (_|_){
713-
+ // [eval] issue3678.y.c: field not allowed:
714-
+ // ./validator_is_top.cue:13:6
715-
+ // ./validator_is_top.cue:19:5
716-
+ }
630+
+ y: (#struct){
631+
c: (string){ "c" }
717632
}
718633
}
719-
}
720634
-- out/eval --
721635
Errors:
722636
callOfCallToValidator.e: cannot call previously called validator b:

internal/core/adt/conjunct.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -740,14 +740,7 @@ func (n *nodeContext) insertValueConjunct(env *Environment, v Value, id CloseInf
740740
case Validator:
741741
// This check serves as simplifier, but also to remove duplicates.
742742
cx := MakeConjunct(env, x, id)
743-
for i, y := range n.checks {
744-
if b, ok := SimplifyValidator(ctx, cx, y); ok {
745-
n.checks[i] = b
746-
return
747-
}
748-
}
749743
kind := x.Kind()
750-
n.updateNodeType(kind, x, id)
751744
// A validator that is inserted in a closeContext should behave like top
752745
// in the sense that the closeContext should not be closed if no other
753746
// value is present that would erase top (cc.hasNonTop): if a field is
@@ -756,6 +749,14 @@ func (n *nodeContext) insertValueConjunct(env *Environment, v Value, id CloseInf
756749
if kind&(ListKind|StructKind) != 0 {
757750
id.cc.hasTop = true
758751
}
752+
753+
for i, y := range n.checks {
754+
if b, ok := SimplifyValidator(ctx, cx, y); ok {
755+
n.checks[i] = b
756+
return
757+
}
758+
}
759+
759760
n.checks = append(n.checks, cx)
760761

761762
// We use set the type of the validator argument here to ensure that

0 commit comments

Comments
 (0)