Skip to content

Commit afe322d

Browse files
NoamTDmvdan
authored andcommitted
internal/pkg: make Len ignore optional fields
The Struct.Len function incorrectly includes optional fields in the total field count. Therefore, `{a?: 1, b?: 2}` is considered to have 2 fields instead of 0. This causes the `struct.MinFields` and `struct.MaxFields` to return incorrect results. To fix this, we now exclude optional fields from the sum. Fixes #2749. Signed-off-by: Noam Dolovich <[email protected]> Change-Id: If92dbd948aae098c20d3c237a22bdb49dcd0a35b Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1194515 Reviewed-by: Daniel Martí <[email protected]> Reviewed-by: Marcel van Lohuizen <[email protected]> Unity-Result: CUE porcuepine <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 4ae7530 commit afe322d

File tree

2 files changed

+39
-22
lines changed

2 files changed

+39
-22
lines changed

internal/pkg/types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func (s *Struct) Arcs() []*adt.Vertex {
5050
func (s *Struct) Len() int {
5151
count := 0
5252
for _, a := range s.Arcs() {
53-
if a.Label.IsString() {
53+
if a.Label.IsString() && !s.node.IsOptional(a.Label) {
5454
count++
5555
}
5656
}

pkg/struct/testdata/struct.txtar

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,21 @@ minFields.fail1: invalid value {} (does not satisfy struct.MinFields(1)): len(fi
3636
minFields.failHidden1: invalid value {_a:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1):
3737
./in.cue:4:12
3838
./in.cue:4:29
39+
minFields.failOptional1: invalid value {a?:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1):
40+
./in.cue:4:12
41+
./in.cue:4:29
3942
maxFields.fail1: invalid value {a:1,b:2} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1):
4043
./in.cue:18:12
4144
./in.cue:18:29
42-
maxFields.ok4: invalid value {a?:1,b?:2} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1):
43-
./in.cue:18:12
44-
./in.cue:18:29
4545

4646
Result:
4747
import "struct"
4848

4949
minFields: {
5050
incomplete1: {} & struct.MinFields(1)
51-
fail1: _|_ // minFields.fail1: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
52-
failOptional1: {
53-
a?: 1
54-
}
55-
failHidden1: _|_ // minFields.failHidden1: invalid value {_a:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
51+
fail1: _|_ // minFields.fail1: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
52+
failOptional1: _|_ // minFields.failOptional1: invalid value {a?:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
53+
failHidden1: _|_ // minFields.failHidden1: invalid value {_a:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
5654
ok4: {
5755
a: 1
5856
}
@@ -78,7 +76,10 @@ maxFields: {
7876
ok3: {
7977
a: 1
8078
}
81-
ok4: _|_ // maxFields.ok4: invalid value {a?:1,b?:2} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1)
79+
ok4: {
80+
a?: 1
81+
b?: 2
82+
}
8283
ok5: {
8384
a: 1
8485
}
@@ -88,11 +89,14 @@ maxFields: {
8889
}
8990
fail1: _|_ // maxFields.fail1: invalid value {a:1,b:2} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1)
9091
}
92+
-- diff/explanation --
93+
failOptional1: the new evaluator fails as expected, but the old evaluator doesn't -
94+
perhaps due to a bug in either the old evaluator or test code.
9195
-- diff/-out/structs-v3<==>+out/structs --
9296
diff old new
9397
--- old
9498
+++ new
95-
@@ -2,19 +2,15 @@
99+
@@ -2,15 +2,15 @@
96100
minFields.fail1: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1):
97101
./in.cue:4:12
98102
./in.cue:4:29
@@ -101,17 +105,31 @@ diff old new
101105
./in.cue:4:12
102106
./in.cue:4:29
103107
- ./in.cue:9:15
108+
+minFields.failOptional1: invalid value {a?:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1):
109+
+ ./in.cue:4:12
110+
+ ./in.cue:4:29
104111
maxFields.fail1: invalid value {a:1,b:2} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1):
105112
./in.cue:18:12
106113
./in.cue:18:29
107114
- ./in.cue:27:9
108-
maxFields.ok4: invalid value {a?:1,b?:2} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1):
109-
./in.cue:18:12
110-
./in.cue:18:29
111-
- ./in.cue:23:7
112115

113116
Result:
114117
import "struct"
118+
@@ -17,11 +17,9 @@
119+
120+
minFields: {
121+
incomplete1: {} & struct.MinFields(1)
122+
- fail1: _|_ // minFields.fail1: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
123+
- failOptional1: close({
124+
- a?: 1
125+
- }) & struct.MinFields(1)
126+
- failHidden1: _|_ // minFields.failHidden1: invalid value {_a:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
127+
+ fail1: _|_ // minFields.fail1: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
128+
+ failOptional1: _|_ // minFields.failOptional1: invalid value {a?:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
129+
+ failHidden1: _|_ // minFields.failHidden1: invalid value {_a:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
130+
ok4: {
131+
a: 1
132+
}
115133
-- diff/todo/p2 --
116134
Missing error positions.
117135
-- out/structs --
@@ -128,20 +146,16 @@ maxFields.fail1: invalid value {a:1,b:2} (does not satisfy struct.MaxFields(1)):
128146
./in.cue:18:12
129147
./in.cue:18:29
130148
./in.cue:27:9
131-
maxFields.ok4: invalid value {a?:1,b?:2} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1):
132-
./in.cue:18:12
133-
./in.cue:18:29
134-
./in.cue:23:7
135149

136150
Result:
137151
import "struct"
138152

139153
minFields: {
140154
incomplete1: {} & struct.MinFields(1)
141155
fail1: _|_ // minFields.fail1: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
142-
failOptional1: {
156+
failOptional1: close({
143157
a?: 1
144-
}
158+
}) & struct.MinFields(1)
145159
failHidden1: _|_ // minFields.failHidden1: invalid value {_a:1} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1)
146160
ok4: {
147161
a: 1
@@ -168,7 +182,10 @@ maxFields: {
168182
ok3: {
169183
a: 1
170184
}
171-
ok4: _|_ // maxFields.ok4: invalid value {a?:1,b?:2} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1)
185+
ok4: {
186+
a?: 1
187+
b?: 2
188+
}
172189
ok5: {
173190
a: 1
174191
}

0 commit comments

Comments
 (0)