-- in.cue --
// cycle is a structural cycle
cycle: a: cycle

// reference to outside structural cycle
r1a: cycle | int
r1b: int | cycle

r2a: cycle | 1
r2b: 1 | cycle

r3a: cycle | null
r3b: null | cycle

r4a: cycle | {}
r4b: {} | cycle

r5a: cycle | []
r5b: [] | cycle

// reference to ancestor node
s1a: x: s1a | int
s1b: x: int | s1b

s2a: x: s2a | 1
s2b: x: 1 | s2b

s3a: x: s3a | null
s3b: x: null | s3b

s4a: x: s4a | {}
s4b: x: {} | s4b

s5a: x: s5a | []
s5b: x: [] | s5b

-- issue3042.cue --
issue3042: {
	// Recursively, any field named "name" should begin with "foo".
	// The data value below should then fail.
	#foo: =~"^foo"
	#nesting: string | {name?: #foo, [string]: #nesting} | [...#nesting]

	data: #nesting & {
		secret: {
			infra: [
				{name: "bar1"}
			]
		}
	}
}
-- out/eval/stats --
Leaks:  0
Freed:  199
Reused: 181
Allocs: 18
Retain: 0

Unifications: 93
Conjuncts:    280
Disjuncts:    199
-- out/eval --
Errors:
cycle.a: structural cycle

Result:
(_|_){
  // [structural cycle]
  cycle: (_|_){
    // [structural cycle]
    a: (_|_){
      // [structural cycle] cycle.a: structural cycle
    }
  }
  r1a: (int){ int }
  r1b: (int){ int }
  r2a: (int){ 1 }
  r2b: (int){ 1 }
  r3a: (null){ null }
  r3b: (null){ null }
  r4a: (struct){
  }
  r4b: (struct){
  }
  r5a: (#list){
  }
  r5b: (#list){
  }
  s1a: (struct){
    x: (int){ int }
  }
  s1b: (struct){
    x: (int){ int }
  }
  s2a: (struct){
    x: (int){ 1 }
  }
  s2b: (struct){
    x: (int){ 1 }
  }
  s3a: (struct){
    x: (null){ null }
  }
  s3b: (struct){
    x: (null){ null }
  }
  s4a: (struct){
    x: (struct){
    }
  }
  s4b: (struct){
    x: (struct){
    }
  }
  s5a: (struct){
    x: (#list){
    }
  }
  s5b: (struct){
    x: (#list){
    }
  }
  issue3042: (struct){
    #foo: (string){ =~"^foo" }
    #nesting: ((string|list|struct)){ |((string){ string }, (#struct){
        name?: (string){ =~"^foo" }
      }, (list){
      }) }
    data: (#struct){
      secret: (#struct){
        infra: (#list){
          0: (struct){
            name: (string){ "bar1" }
          }
        }
        name?: (string){ =~"^foo" }
      }
      name?: (string){ =~"^foo" }
    }
  }
}
-- out/evalalpha --
Errors:
cycle.a: structural cycle
issue3042.data: 2 errors in empty disjunction:
issue3042.data: conflicting values [...#nesting] and {secret:{infra:[{name:"bar1"}]}} (mismatched types list and struct):
    ./issue3042.cue:5:57
    ./issue3042.cue:7:19
issue3042.data: conflicting values string and {secret:{infra:[{name:"bar1"}]}} (mismatched types string and struct):
    ./issue3042.cue:5:12
    ./issue3042.cue:7:19

Result:
(_|_){
  // [eval]
  cycle: (_|_){
    // [structural cycle]
    a: (_|_){
      // [structural cycle] cycle.a: structural cycle
    }
  }
  r1a: (int){ int }
  r1b: (int){ int }
  r2a: (int){ 1 }
  r2b: (int){ 1 }
  r3a: (null){ null }
  r3b: (null){ null }
  r4a: (struct){
  }
  r4b: (struct){
  }
  r5a: (#list){
  }
  r5b: (#list){
  }
  s1a: (struct){
    x: (int){ int }
  }
  s1b: (struct){
    x: (int){ int }
  }
  s2a: (struct){
    x: (int){ 1 }
  }
  s2b: (struct){
    x: (int){ 1 }
  }
  s3a: (struct){
    x: (null){ null }
  }
  s3b: (struct){
    x: (null){ null }
  }
  s4a: (struct){
    x: (struct){
    }
  }
  s4b: (struct){
    x: (struct){
    }
  }
  s5a: (struct){
    x: (#list){
    }
  }
  s5b: (struct){
    x: (#list){
    }
  }
  issue3042: (_|_){
    // [eval]
    #foo: (string){ =~"^foo" }
    #nesting: ((string|list|struct)){ |((string){ string }, (#struct){
        name?: (string){ =~"^foo" }
      }, (list){
      }) }
    data: (_|_){
      // [eval] issue3042.data: 2 errors in empty disjunction:
      // issue3042.data: conflicting values [...#nesting] and {secret:{infra:[{name:"bar1"}]}} (mismatched types list and struct):
      //     ./issue3042.cue:5:57
      //     ./issue3042.cue:7:19
      // issue3042.data: conflicting values string and {secret:{infra:[{name:"bar1"}]}} (mismatched types string and struct):
      //     ./issue3042.cue:5:12
      //     ./issue3042.cue:7:19
      secret: (struct){
        infra: (list){ list }
      }
    }
  }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -1,9 +1,16 @@
 Errors:
 cycle.a: structural cycle
+issue3042.data: 2 errors in empty disjunction:
+issue3042.data: conflicting values [...#nesting] and {secret:{infra:[{name:"bar1"}]}} (mismatched types list and struct):
+    ./issue3042.cue:5:57
+    ./issue3042.cue:7:19
+issue3042.data: conflicting values string and {secret:{infra:[{name:"bar1"}]}} (mismatched types string and struct):
+    ./issue3042.cue:5:12
+    ./issue3042.cue:7:19
 
 Result:
 (_|_){
-  // [structural cycle]
+  // [eval]
   cycle: (_|_){
     // [structural cycle]
     a: (_|_){
@@ -58,22 +65,24 @@
     x: (#list){
     }
   }
-  issue3042: (struct){
+  issue3042: (_|_){
+    // [eval]
     #foo: (string){ =~"^foo" }
     #nesting: ((string|list|struct)){ |((string){ string }, (#struct){
         name?: (string){ =~"^foo" }
       }, (list){
       }) }
-    data: (#struct){
-      secret: (#struct){
-        infra: (#list){
-          0: (struct){
-            name: (string){ "bar1" }
-          }
-        }
-        name?: (string){ =~"^foo" }
+    data: (_|_){
+      // [eval] issue3042.data: 2 errors in empty disjunction:
+      // issue3042.data: conflicting values [...#nesting] and {secret:{infra:[{name:"bar1"}]}} (mismatched types list and struct):
+      //     ./issue3042.cue:5:57
+      //     ./issue3042.cue:7:19
+      // issue3042.data: conflicting values string and {secret:{infra:[{name:"bar1"}]}} (mismatched types string and struct):
+      //     ./issue3042.cue:5:12
+      //     ./issue3042.cue:7:19
+      secret: (struct){
+        infra: (list){ list }
       }
-      name?: (string){ =~"^foo" }
     }
   }
 }
-- diff/explanation --
issue3042: The old evaluator incorrectly resolved to a concrete value,
whereas the new evaluator correctly spots that data.secret.infra.name does not unify with #foo.
The new closedness of evalv3 may hide such errors by reporting a spurious
"field not allowed" error.
-- out/compile --
--- in.cue
{
  cycle: {
    a: 〈1;cycle〉
  }
  r1a: (〈0;cycle〉|int)
  r1b: (int|〈0;cycle〉)
  r2a: (〈0;cycle〉|1)
  r2b: (1|〈0;cycle〉)
  r3a: (〈0;cycle〉|null)
  r3b: (null|〈0;cycle〉)
  r4a: (〈0;cycle〉|{})
  r4b: ({}|〈0;cycle〉)
  r5a: (〈0;cycle〉|[])
  r5b: ([]|〈0;cycle〉)
  s1a: {
    x: (〈1;s1a〉|int)
  }
  s1b: {
    x: (int|〈1;s1b〉)
  }
  s2a: {
    x: (〈1;s2a〉|1)
  }
  s2b: {
    x: (1|〈1;s2b〉)
  }
  s3a: {
    x: (〈1;s3a〉|null)
  }
  s3b: {
    x: (null|〈1;s3b〉)
  }
  s4a: {
    x: (〈1;s4a〉|{})
  }
  s4b: {
    x: ({}|〈1;s4b〉)
  }
  s5a: {
    x: (〈1;s5a〉|[])
  }
  s5b: {
    x: ([]|〈1;s5b〉)
  }
}
--- issue3042.cue
{
  issue3042: {
    #foo: =~"^foo"
    #nesting: (string|{
      name?: 〈1;#foo〉
      [string]: 〈1;#nesting〉
    }|[
      ...〈1;#nesting〉,
    ])
    data: (〈0;#nesting〉 & {
      secret: {
        infra: [
          {
            name: "bar1"
          },
        ]
      }
    })
  }
}
