Skip to content

Commit cd2107a

Browse files
committed
internal/core/adt: closedness fix related to comprehension
This consists of two fixes: 1. use allows instead of matchPattern to check for fields that are not covered by patterns. 2. updates the arcTypes _after_ calling allows, as allows needs the old values. Fixes #3486 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: I85c04f814bf0cb67a2a57dc10205ad2a309cb61f Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1202421 Unity-Result: CUE porcuepine <[email protected]> Reviewed-by: Daniel Martí <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 6916b5b commit cd2107a

File tree

3 files changed

+91
-13
lines changed

3 files changed

+91
-13
lines changed

cue/testdata/comprehensions/closed.txtar

+84-9
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,27 @@ issue3483: {
9999
}
100100
}
101101
}
102+
issue3486: {
103+
#schema: {}
104+
105+
if true {
106+
out: {
107+
#schema
108+
// This field should be allowed as #schema is embedded.
109+
extra: "foo"
110+
}
111+
}
112+
}
102113
-- out/eval/stats --
103114
Leaks: 2
104-
Freed: 76
105-
Reused: 70
115+
Freed: 80
116+
Reused: 74
106117
Allocs: 8
107118
Retain: 3
108119

109-
Unifications: 64
110-
Conjuncts: 112
111-
Disjuncts: 77
120+
Unifications: 68
121+
Conjuncts: 118
122+
Disjuncts: 81
112123
-- out/evalalpha --
113124
Errors:
114125
noEraseDefinition.a.0.b: field not allowed:
@@ -229,12 +240,19 @@ Result:
229240
}
230241
}
231242
}
243+
issue3486: (struct){
244+
#schema: (#struct){
245+
}
246+
out: (#struct){
247+
extra: (string){ "foo" }
248+
}
249+
}
232250
}
233251
-- diff/-out/evalalpha<==>+out/eval --
234252
diff old new
235253
--- old
236254
+++ new
237-
@@ -1,15 +1,10 @@
255+
@@ -1,20 +1,10 @@
238256
Errors:
239257
+noEraseDefinition.a.0.b: field not allowed:
240258
+ ./in.cue:55:17
@@ -246,14 +264,19 @@ diff old new
246264
./in.cue:28:4
247265
- ./in.cue:32:8
248266
./in.cue:32:14
267+
-issue3486.out.extra: field not allowed:
268+
- ./v3issues.cue:10:11
269+
- ./v3issues.cue:12:2
270+
- ./v3issues.cue:14:4
271+
- ./v3issues.cue:16:4
249272
-noEraseDefinition.a.0.b: field not allowed:
250273
- ./in.cue:54:17
251274
- ./in.cue:55:7
252275
- ./in.cue:55:17
253276

254277
Result:
255278
(_|_){
256-
@@ -45,11 +40,8 @@
279+
@@ -50,11 +40,8 @@
257280
// [eval]
258281
d: (_|_){
259282
// [eval] disallowed.vErr.d: field not allowed:
@@ -266,7 +289,7 @@ diff old new
266289
// ./in.cue:32:14
267290
}
268291
}
269-
@@ -78,13 +70,11 @@
292+
@@ -83,13 +70,11 @@
270293
// [eval]
271294
0: (_|_){
272295
// [eval]
@@ -281,7 +304,7 @@ diff old new
281304
}
282305
}
283306
}
284-
@@ -109,13 +99,11 @@
307+
@@ -114,13 +99,11 @@
285308
c: (_){ _ }
286309
}
287310
out: (#struct){
@@ -297,6 +320,29 @@ diff old new
297320
}
298321
}
299322
}
323+
@@ -134,19 +117,11 @@
324+
}
325+
}
326+
}
327+
- issue3486: (_|_){
328+
- // [eval]
329+
+ issue3486: (struct){
330+
#schema: (#struct){
331+
}
332+
- out: (_|_){
333+
- // [eval]
334+
- extra: (_|_){
335+
- // [eval] issue3486.out.extra: field not allowed:
336+
- // ./v3issues.cue:10:11
337+
- // ./v3issues.cue:12:2
338+
- // ./v3issues.cue:14:4
339+
- // ./v3issues.cue:16:4
340+
- }
341+
+ out: (#struct){
342+
+ extra: (string){ "foo" }
343+
}
344+
}
345+
}
300346
-- diff/todo/p3 --
301347
Missing error positions.
302348
-- diff/explanation --
@@ -310,6 +356,11 @@ disallowed.vErr.d: field not allowed:
310356
./in.cue:28:4
311357
./in.cue:32:8
312358
./in.cue:32:14
359+
issue3486.out.extra: field not allowed:
360+
./v3issues.cue:10:11
361+
./v3issues.cue:12:2
362+
./v3issues.cue:14:4
363+
./v3issues.cue:16:4
313364
noEraseDefinition.a.0.b: field not allowed:
314365
./in.cue:54:17
315366
./in.cue:55:7
@@ -433,6 +484,21 @@ Result:
433484
}
434485
}
435486
}
487+
issue3486: (_|_){
488+
// [eval]
489+
#schema: (#struct){
490+
}
491+
out: (_|_){
492+
// [eval]
493+
extra: (_|_){
494+
// [eval] issue3486.out.extra: field not allowed:
495+
// ./v3issues.cue:10:11
496+
// ./v3issues.cue:12:2
497+
// ./v3issues.cue:14:4
498+
// ./v3issues.cue:16:4
499+
}
500+
}
501+
}
436502
}
437503
-- out/compile --
438504
--- in.cue
@@ -554,4 +620,13 @@ Result:
554620
})
555621
}
556622
}
623+
issue3486: {
624+
#schema: {}
625+
if true {
626+
out: {
627+
〈2;#schema〉
628+
extra: "foo"
629+
}
630+
}
631+
}
557632
}

internal/core/adt/comprehension.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -478,14 +478,15 @@ func (n *nodeContext) processComprehensionInner(d *envYield, state vertexStatus)
478478
// because the parent referrer will reach a zero count before this
479479
// node will reach a zero count, we need to propagate the arcType.
480480
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+
}
481486
// TODO: remove this line once we use the arcType of the
482487
// closeContext in notAllowedError.
483488
arc.src.updateArcType(c.arcType)
484-
t := arc.arcType
485489
arc.updateArcType(c.arcType)
486-
if p.isClosed && t >= ArcPending && !matchPattern(ctx, p.Expr, f) {
487-
ctx.notAllowedError(p.src, arc.src)
488-
}
489490
}
490491
v.updateArcType(c.arcType)
491492
if v.ArcType == ArcNotPresent {

internal/core/adt/constraints.go

+2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ func (n *nodeContext) insertConstraint(pattern Value, c Conjunct) bool {
109109

110110
// matchPattern reports whether f matches pattern. The result reflects
111111
// whether unification of pattern with f converted to a CUE value succeeds.
112+
// The caller should check separately whether f matches any other arcs
113+
// that are not covered by pattern.
112114
func matchPattern(ctx *OpContext, pattern Value, f Feature) bool {
113115
if pattern == nil || !f.IsRegular() {
114116
return false

0 commit comments

Comments
 (0)