-- in.cue -- a: *1 | int aa: *1 | *2 | int b: { name: "int" val: int } | { name: "str" val: string } d: b & {val: 3} c: b & {name: "int", val: 3} e: b & {val: "foo"} f: b & {name: "str", val: 3} // Disjunct elimination based on type. e1: { a: null | {bar: 2} b: (a & {}).bar } d1: { a: (null | {c: 1}) & {} b: {} & (null | {c: 1}) } d2: { a: ([...] | {c: 1}) & {} b: {} & ([...] | {c: 1}) } d3: { a: (string | {c: 1}) & {} b: {} & (string | {c: 1}) } d4: { a: (string | {c: 1}) & {} b: {} & (string | {c: 1}) } d5: { a: (number | {c: 1}) & {} b: {} & (number | {c: 1}) } d6: { a: (int | {c: 1}) & {} b: {} & (int | {c: 1}) } t10: { schema: test schema: string | {name: string} #A: {string | {name: string}} test: name: "Test" test: #A } t10: { schema: string | {name: string} schema: test #A: {string | {name: string}} test: name: "Test" test: #A } t10: { #A: {string | {name: string}} test: name: "Test" test: #A schema: string | {name: string} schema: test } t11: { a: #A a: b b: #A & ["b"] #A: ["a" | "b"] | {} } t11: { b: #A & ["b"] #A: ["a" | "b"] | {} a: b a: #A } cross: { a: *"word" | string a: string | *"word" } d100: { // Should we allow a selector to imply a struct or list? Would be convenient. // This would be a spec change. Disallow for now. i: null | {bar: 2} j: i.bar } issue641: { #A: { type: "a" x: "" } #B: { type: "b" x: string } #C: { b: #A | #B } e: [string]: #C & { b: #A | #B } e: foobar: #C & { b: #B & { x: "foobar" } } } -- out/eval/stats -- Leaks: 0 Freed: 304 Reused: 292 Allocs: 12 Retain: 0 Unifications: 147 Conjuncts: 564 Disjuncts: 304 -- out/eval -- Errors: f: 2 errors in empty disjunction: f.name: conflicting values "int" and "str": ./in.cue:5:8 ./in.cue:15:4 ./in.cue:15:15 f.val: conflicting values 3 and string (mismatched types int and string): ./in.cue:9:8 ./in.cue:15:4 ./in.cue:15:27 Result: (_|_){ // [eval] a: (int){ |(*(int){ 1 }, (int){ int }) } aa: (int){ |(*(int){ 1 }, *(int){ 2 }, (int){ int }) } b: (struct){ |((struct){ name: (string){ "int" } val: (int){ int } }, (struct){ name: (string){ "str" } val: (string){ string } }) } d: (struct){ val: (int){ 3 } name: (string){ "int" } } c: (struct){ name: (string){ "int" } val: (int){ 3 } } e: (struct){ val: (string){ "foo" } name: (string){ "str" } } f: (_|_){ // [eval] f: 2 errors in empty disjunction: // f.name: conflicting values "int" and "str": // ./in.cue:5:8 // ./in.cue:15:4 // ./in.cue:15:15 // f.val: conflicting values 3 and string (mismatched types int and string): // ./in.cue:9:8 // ./in.cue:15:4 // ./in.cue:15:27 name: (string){ "str" } val: (_|_){ // [eval] f.val: conflicting values 3 and string (mismatched types int and string): // ./in.cue:9:8 // ./in.cue:15:4 // ./in.cue:15:27 } } e1: (struct){ a: ((null|struct)){ |((null){ null }, (struct){ bar: (int){ 2 } }) } b: (int){ 2 } } d1: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d2: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d3: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d4: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d5: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d6: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } t10: (struct){ schema: (#struct){ name: (string){ "Test" } } #A: ((string|struct)){ |((string){ string }, (#struct){ name: (string){ string } }) } test: (#struct){ name: (string){ "Test" } } } t11: (struct){ a: (#list){ 0: (string){ "b" } } b: (#list){ 0: (string){ "b" } } #A: ((list|struct)){ |((#list){ 0: (string){ |((string){ "a" }, (string){ "b" }) } }, (#struct){ }) } } cross: (struct){ a: (string){ |(*(string){ "word" }, (string){ string }) } } d100: (struct){ i: ((null|struct)){ |((null){ null }, (struct){ bar: (int){ 2 } }) } j: (_|_){ // [incomplete] d100.j: unresolved disjunction null | {bar:2} (type (null|struct)): // ./in.cue:106:5 } } issue641: (struct){ #A: (#struct){ type: (string){ "a" } x: (string){ "" } } #B: (#struct){ type: (string){ "b" } x: (string){ string } } #C: (#struct){ b: (#struct){ |((#struct){ type: (string){ "a" } x: (string){ "" } }, (#struct){ type: (string){ "b" } x: (string){ string } }) } } e: (struct){ foobar: (#struct){ b: (#struct){ type: (string){ "b" } x: (string){ "foobar" } } } } } } -- out/compile -- --- in.cue { a: (*1|int) aa: (*1|*2|int) b: ({ name: "int" val: int }|{ name: "str" val: string }) d: (〈0;b〉 & { val: 3 }) c: (〈0;b〉 & { name: "int" val: 3 }) e: (〈0;b〉 & { val: "foo" }) f: (〈0;b〉 & { name: "str" val: 3 }) e1: { a: (null|{ bar: 2 }) b: (〈0;a〉 & {}).bar } d1: { a: ((null|{ c: 1 }) & {}) b: ({} & (null|{ c: 1 })) } d2: { a: (([ ..., ]|{ c: 1 }) & {}) b: ({} & ([ ..., ]|{ c: 1 })) } d3: { a: ((string|{ c: 1 }) & {}) b: ({} & (string|{ c: 1 })) } d4: { a: ((string|{ c: 1 }) & {}) b: ({} & (string|{ c: 1 })) } d5: { a: ((number|{ c: 1 }) & {}) b: ({} & (number|{ c: 1 })) } d6: { a: ((int|{ c: 1 }) & {}) b: ({} & (int|{ c: 1 })) } t10: { schema: 〈0;test〉 schema: (string|{ name: string }) #A: { (string|{ name: string }) } test: { name: "Test" } test: 〈0;#A〉 } t10: { schema: (string|{ name: string }) schema: 〈0;test〉 #A: { (string|{ name: string }) } test: { name: "Test" } test: 〈0;#A〉 } t10: { #A: { (string|{ name: string }) } test: { name: "Test" } test: 〈0;#A〉 schema: (string|{ name: string }) schema: 〈0;test〉 } t11: { a: 〈0;#A〉 a: 〈0;b〉 b: (〈0;#A〉 & [ "b", ]) #A: ([ ("a"|"b"), ]|{}) } t11: { b: (〈0;#A〉 & [ "b", ]) #A: ([ ("a"|"b"), ]|{}) a: 〈0;b〉 a: 〈0;#A〉 } cross: { a: (*"word"|string) a: (string|*"word") } d100: { i: (null|{ bar: 2 }) j: 〈0;i〉.bar } issue641: { #A: { type: "a" x: "" } #B: { type: "b" x: string } #C: { b: (〈1;#A〉|〈1;#B〉) } e: { [string]: (〈1;#C〉 & { b: (〈2;#A〉|〈2;#B〉) }) } e: { foobar: (〈1;#C〉 & { b: (〈2;#B〉 & { x: "foobar" }) }) } } }