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  }