cuelang.org/go@v0.13.0/cue/testdata/disjunctions/edge.txtar (about) 1 # This file mostly contains edge cases of disjunction semantics. 2 # We should ensure that all these cases can be derived from thee spec. 3 # 4 # Many of these cases were discovered as part of the development of the new 5 # evaluator that started at v0.7 and do not pass for that version. 6 -- in.cue -- 7 cyclicalInsertInDisjunction: { 8 // We do not allow lookups across unresolved disjunctions. As such, the 9 // references across disjunctions are not allowed to disambiguate a 10 // disjunction. 11 // 12 // Algorithmically, the distinction between allowing this or not is 13 // achieved by allowing dereferencing of the node in which a disjunction 14 // occurs to the disjunct under evaluation. Effectively this is what the 15 // v0.6 evaluator does. 16 17 ok1: { 18 // In this case, unifying the comprehension into the processing of the 19 // disjunctions would _not_ case the reference to cross disjunction 20 // boundaries. 21 c: {d: e, e: _} 22 c: {d: 1, e: 2} | {d : 2, e: 2} 23 } 24 maybe1: { 25 // In this case, the reference c.e crosses a disjunction boundary. 26 // However, since the reference starts from within a disjunction, this 27 // could be allowed, if we define it to be. 28 c: d: c.e 29 c: {d: 1, e: 2} | {d : 2, e: 2} 30 } 31 err1: { 32 // This should be an error: to resolve x in c.d, we need to first 33 // resolve x to a concrete value. As `x` is defined outside the 34 // disjunction, and the disjunction cannot be resolved without it, `x` 35 // cannot be evaluated to a concrete value, resulting in an error. 36 x: c.e 37 c: d: x 38 c: {d: 1, e: 2} | {d : 2, e: 2} 39 } 40 err2: { 41 // This is a more obviously erroneous variant of err1. The div in x 42 // requires a concrete value for c.e. However, the disjunction can only 43 // be disambiguated as a result of computing x. This means c.e cannot 44 // be concrete at the time of evaluation. 45 x: div(c.e, 2) 46 c: d: x 47 c: {d: 1, e: 2} | {d : 2, e: 3} 48 } 49 err3: { 50 // Here it is clear that d will not disambiguate the disjunction at c. 51 // So c.e. cannot be resolved. 52 x: c.e 53 c: d: 1 | 2 | x 54 c: {d: 1, e: 2} | {d : 2, e: 3} 55 } 56 } 57 58 preseveBottomSemantics: ok: { 59 // `a: a`, which just says that `a` is `a`, is logically equivalent to 60 // `a: _`. Consequently, the disjunction `a: a | X` is equivalent to 61 // `a: _ | X`. As we do not simplify disjunctions, the result is `a: _ | X`. 62 // However, we could consider simplifying in this case to `a: _` if we can 63 // come up with a good general mechanism for subsumption. 64 #x: { #x | {} } 65 } 66 67 eliminateOpenVariant: ok: { 68 // We have two structs in the disjunction that are identical in every way 69 // except openness. TODO: should we disambiguate those? 70 c: {a: 1} | #b 71 #b: {a: 1} 72 } 73 74 cyclicSelfElimination: ok: { 75 // This should resolve to {y: 1} (works for new evaluator) 76 y: 1 | {y: 1} 77 y 78 } 79 -- panic.cue -- 80 // This used to cause a panic with evalv3. 81 panic1: { 82 #TypeFoo: { 83 name: "foo" 84 // Make foo_field here optional and master panics too! 85 foo_field: string 86 } 87 #TypeBar: { 88 #TypeBar2 89 bar_field?: string 90 } 91 92 #TypeBar2: name: "bar" 93 94 objs: obj1: { 95 type: #TypeFoo | #TypeBar 96 type: *objs["missing"] | #TypeFoo | #TypeBar 97 } 98 99 out: #TypeFoo | #TypeBar 100 out: objs["obj1"].type 101 } 102 -- out/eval/stats -- 103 Leaks: 0 104 Freed: 152 105 Reused: 141 106 Allocs: 11 107 Retain: 12 108 109 Unifications: 108 110 Conjuncts: 237 111 Disjuncts: 154 112 -- out/eval -- 113 (struct){ 114 cyclicalInsertInDisjunction: (struct){ 115 ok1: (struct){ 116 c: (struct){ 117 d: (int){ 2 } 118 e: (int){ 2 } 119 } 120 } 121 maybe1: (struct){ 122 c: (struct){ 123 d: (int){ 2 } 124 e: (int){ 2 } 125 } 126 } 127 err1: (struct){ 128 x: (int){ 2 } 129 c: (struct){ 130 d: (int){ 2 } 131 e: (int){ 2 } 132 } 133 } 134 err2: (struct){ 135 x: (int){ 1 } 136 c: (struct){ 137 d: (int){ 1 } 138 e: (int){ 2 } 139 } 140 } 141 err3: (struct){ 142 x: (_|_){ 143 // [incomplete] cyclicalInsertInDisjunction.err3.x: unresolved disjunction {d:1,e:2} | {d:2,e:3} (type struct): 144 // ./in.cue:46:6 145 } 146 c: (struct){ |((struct){ 147 d: (int){ 1 } 148 e: (int){ 2 } 149 }, (struct){ 150 d: (int){ 2 } 151 e: (int){ 3 } 152 }) } 153 } 154 } 155 preseveBottomSemantics: (struct){ 156 ok: (struct){ 157 #x: (#struct){ 158 } 159 } 160 } 161 eliminateOpenVariant: (struct){ 162 ok: (struct){ 163 c: (#struct){ |((struct){ 164 a: (int){ 1 } 165 }, (#struct){ 166 a: (int){ 1 } 167 }) } 168 #b: (#struct){ 169 a: (int){ 1 } 170 } 171 } 172 } 173 cyclicSelfElimination: (struct){ 174 ok: (_|_){ 175 // [incomplete] cyclicSelfElimination.ok: 2 errors in empty disjunction: 176 // cyclicSelfElimination.ok: conflicting values 1 and {y:(1|{y:1}),y} (mismatched types int and struct): 177 // ./in.cue:68:28 178 // ./in.cue:70:5 179 // cyclicSelfElimination.ok: cannot add field y: was already used: 180 // ./in.cue:70:10 181 y: ((int|struct)){ |((int){ 1 }, (struct){ 182 y: (int){ 1 } 183 }) } 184 } 185 } 186 panic1: (struct){ 187 #TypeFoo: (#struct){ 188 name: (string){ "foo" } 189 foo_field: (string){ string } 190 } 191 #TypeBar: (#struct){ 192 name: (string){ "bar" } 193 bar_field?: (string){ string } 194 } 195 #TypeBar2: (#struct){ 196 name: (string){ "bar" } 197 } 198 objs: (struct){ 199 obj1: (struct){ 200 type: (#struct){ |((#struct){ 201 name: (string){ "foo" } 202 foo_field: (string){ string } 203 }, (#struct){ 204 name: (string){ "bar" } 205 bar_field?: (string){ string } 206 }) } 207 } 208 } 209 out: (#struct){ |((#struct){ 210 name: (string){ "foo" } 211 foo_field: (string){ string } 212 }, (#struct){ 213 name: (string){ "bar" } 214 bar_field?: (string){ string } 215 }) } 216 } 217 } 218 -- out/evalalpha -- 219 (struct){ 220 cyclicalInsertInDisjunction: (struct){ 221 ok1: (struct){ 222 c: (struct){ 223 d: (int){ 2 } 224 e: (int){ 2 } 225 } 226 } 227 maybe1: (struct){ 228 c: (struct){ 229 d: (int){ 2 } 230 e: (int){ 2 } 231 } 232 } 233 err1: (struct){ 234 x: (int){ 2 } 235 c: (struct){ 236 d: (int){ 2 } 237 e: (int){ 2 } 238 } 239 } 240 err2: (struct){ 241 x: (int){ 1 } 242 c: (struct){ 243 d: (int){ 1 } 244 e: (int){ 2 } 245 } 246 } 247 err3: (struct){ 248 x: (_|_){ 249 // [incomplete] cyclicalInsertInDisjunction.err3.x: unresolved disjunction {d:1,e:2} | {d:2,e:3} (type struct): 250 // ./in.cue:46:6 251 } 252 c: (struct){ |((struct){ 253 d: (int){ 1 } 254 e: (int){ 2 } 255 }, (struct){ 256 d: (int){ 2 } 257 e: (int){ 3 } 258 }) } 259 } 260 } 261 preseveBottomSemantics: (struct){ 262 ok: (struct){ 263 #x: (#struct){ 264 } 265 } 266 } 267 eliminateOpenVariant: (struct){ 268 ok: (struct){ 269 c: (struct){ |((struct){ 270 a: (int){ 1 } 271 }, (#struct){ 272 a: (int){ 1 } 273 }) } 274 #b: (#struct){ 275 a: (int){ 1 } 276 } 277 } 278 } 279 cyclicSelfElimination: (struct){ 280 ok: (struct){ 281 y: (int){ 1 } 282 } 283 } 284 panic1: (struct){ 285 #TypeFoo: (#struct){ 286 name: (string){ "foo" } 287 foo_field: (string){ string } 288 } 289 #TypeBar: (#struct){ 290 bar_field?: (string){ string } 291 name: (string){ "bar" } 292 } 293 #TypeBar2: (#struct){ 294 name: (string){ "bar" } 295 } 296 objs: (struct){ 297 obj1: (struct){ 298 type: (struct){ |((#struct){ 299 name: (string){ "foo" } 300 foo_field: (string){ string } 301 }, (#struct){ 302 bar_field?: (string){ string } 303 name: (string){ "bar" } 304 }) } 305 } 306 } 307 out: (struct){ |((#struct){ 308 name: (string){ "foo" } 309 foo_field: (string){ string } 310 }, (#struct){ 311 bar_field?: (string){ string } 312 name: (string){ "bar" } 313 }) } 314 } 315 } 316 -- diff/-out/evalalpha<==>+out/eval -- 317 diff old new 318 --- old 319 +++ new 320 @@ -48,7 +48,7 @@ 321 } 322 eliminateOpenVariant: (struct){ 323 ok: (struct){ 324 - c: (#struct){ |((struct){ 325 + c: (struct){ |((struct){ 326 a: (int){ 1 } 327 }, (#struct){ 328 a: (int){ 1 } 329 @@ -59,16 +59,8 @@ 330 } 331 } 332 cyclicSelfElimination: (struct){ 333 - ok: (_|_){ 334 - // [incomplete] cyclicSelfElimination.ok: 2 errors in empty disjunction: 335 - // cyclicSelfElimination.ok: conflicting values 1 and {y:(1|{y:1}),y} (mismatched types int and struct): 336 - // ./in.cue:68:28 337 - // ./in.cue:70:5 338 - // cyclicSelfElimination.ok: cannot add field y: was already used: 339 - // ./in.cue:70:10 340 - y: ((int|struct)){ |((int){ 1 }, (struct){ 341 - y: (int){ 1 } 342 - }) } 343 + ok: (struct){ 344 + y: (int){ 1 } 345 } 346 } 347 panic1: (struct){ 348 @@ -77,8 +69,8 @@ 349 foo_field: (string){ string } 350 } 351 #TypeBar: (#struct){ 352 - name: (string){ "bar" } 353 bar_field?: (string){ string } 354 + name: (string){ "bar" } 355 } 356 #TypeBar2: (#struct){ 357 name: (string){ "bar" } 358 @@ -85,21 +77,21 @@ 359 } 360 objs: (struct){ 361 obj1: (struct){ 362 - type: (#struct){ |((#struct){ 363 + type: (struct){ |((#struct){ 364 name: (string){ "foo" } 365 foo_field: (string){ string } 366 }, (#struct){ 367 - name: (string){ "bar" } 368 bar_field?: (string){ string } 369 + name: (string){ "bar" } 370 }) } 371 } 372 } 373 - out: (#struct){ |((#struct){ 374 + out: (struct){ |((#struct){ 375 name: (string){ "foo" } 376 foo_field: (string){ string } 377 }, (#struct){ 378 - name: (string){ "bar" } 379 bar_field?: (string){ string } 380 + name: (string){ "bar" } 381 }) } 382 } 383 } 384 -- diff/todo/p2 -- 385 cyclicalInsertInDisjunction.maybe: discrepancy may be okay 386 cyclicalInsertInDisjunction.err1: should be an err for the old and new evaluator. 387 -- diff/todo/p3 -- 388 preseveBottomSemantics: both the old and new evaluator are incorrect here. 389 The result should be either _ or _|{}. 390 -- diff/explanation -- 391 cyclicalInsertInDisjunction.err2: The new evaluator handles this correctly. 392 eliminateOpenVariant.ok: closedness of c is different. Seems correct, or at 393 least okay. 394 cyclicSelfElimination.ok: The new evaluator handles this correctly. 395 -- out/compile -- 396 --- in.cue 397 { 398 cyclicalInsertInDisjunction: { 399 ok1: { 400 c: { 401 d: 〈0;e〉 402 e: _ 403 } 404 c: ({ 405 d: 1 406 e: 2 407 }|{ 408 d: 2 409 e: 2 410 }) 411 } 412 maybe1: { 413 c: { 414 d: 〈1;c〉.e 415 } 416 c: ({ 417 d: 1 418 e: 2 419 }|{ 420 d: 2 421 e: 2 422 }) 423 } 424 err1: { 425 x: 〈0;c〉.e 426 c: { 427 d: 〈1;x〉 428 } 429 c: ({ 430 d: 1 431 e: 2 432 }|{ 433 d: 2 434 e: 2 435 }) 436 } 437 err2: { 438 x: div(〈0;c〉.e, 2) 439 c: { 440 d: 〈1;x〉 441 } 442 c: ({ 443 d: 1 444 e: 2 445 }|{ 446 d: 2 447 e: 3 448 }) 449 } 450 err3: { 451 x: 〈0;c〉.e 452 c: { 453 d: (1|2|〈1;x〉) 454 } 455 c: ({ 456 d: 1 457 e: 2 458 }|{ 459 d: 2 460 e: 3 461 }) 462 } 463 } 464 preseveBottomSemantics: { 465 ok: { 466 #x: { 467 (〈1;#x〉|{}) 468 } 469 } 470 } 471 eliminateOpenVariant: { 472 ok: { 473 c: ({ 474 a: 1 475 }|〈0;#b〉) 476 #b: { 477 a: 1 478 } 479 } 480 } 481 cyclicSelfElimination: { 482 ok: { 483 y: (1|{ 484 y: 1 485 }) 486 〈0;y〉 487 } 488 } 489 } 490 --- panic.cue 491 { 492 panic1: { 493 #TypeFoo: { 494 name: "foo" 495 foo_field: string 496 } 497 #TypeBar: { 498 〈1;#TypeBar2〉 499 bar_field?: string 500 } 501 #TypeBar2: { 502 name: "bar" 503 } 504 objs: { 505 obj1: { 506 type: (〈2;#TypeFoo〉|〈2;#TypeBar〉) 507 type: (*〈2;objs〉["missing"]|〈2;#TypeFoo〉|〈2;#TypeBar〉) 508 } 509 } 510 out: (〈0;#TypeFoo〉|〈0;#TypeBar〉) 511 out: 〈0;objs〉["obj1"].type 512 } 513 }