// Tests fields.go

-- in.cue --
// TODO: reorganize ordered on what is tested by name. E.g.
// insertion: longPath: ok: p1: {
//     a: .... @fail()
// }

ok: t1: {
	c: #R
	c: [{b: int}]
	#R: [...]
}

ok: t2: {
	#A: _
	l: #A
	l: f: "hi"
}

ok: t3: {
	#A: f: {...}
	#A1: { #A }
	s: [string]: #A1
	s: foo: f: d: foo: 1
}

ok: t4: {
	#T: { a: b: 1 }
	W: {
		{#T}
		b: c: 2
	}
}

ok: t5: {
	// TODO: move to err
	#A: {
		Common
		_
	}
	Common: { }
	x: #A
	x: c: int
}

ok: t6: {
	#A: {
		Common
		...
	}
	Common: { }
	x: #A
	x: c: int
}

ok: t7: {
	a: {#A, #B}
	#A: b: f: 1
	#B: b: g: 1
}

ok: t8: {
	// TODO: this should pass
	foo: #X
	#X: {
		a: b: c: C: 1
		for k, _ in a {
			// dynamic field causes insertion one level higher. This causes
			// b to be inserted in a, after it has been referenced.
			a: (k): c: D: 2
		}
	}
}

ok: t9: {
	c: #R
	c: [{b: int}]
	#R: [...]
}

ok: t10: {
	#A: _ // top should allow everything
	l: #A
	l: f: "hi"
}

ok: t11: {
	// indirections
	#A: f: {...}
	#A1: { #A }
	s: [string]: #A1
	s: foo: f: d: foo: "bar" // should pass
}

ok: t12: {
	// nested embedding
	#T: { a: b: 1 }
	W: {
		{#T}
		b: c: 2
	}
}

ok: t13: {
	// TODO: move to err

	// top DOES NOT open up
	#A: {
		Common
		_
	}
	Common: { }
	x: #A
	x: c: int
}

ok: t14: {
	// ellipsis opens up
	#A: {
		Common
		...
	}
	Common: { }
	x: #A
	x: c: int
}

// TODO: move this test to "ok": _ means any and implicitly defines all fields
// to be present as optional fields with _, recursively (as long as the type
// has not been picked to be non-struct).
// This was not observed in V2, but is now observed in V3. We should probably
// either allow for an error variant that only "allows" all fields but does not
// define them as optional top, or rethink the closedness model altogether.
err: t1: {
	#D: _ & {a: 2}
	a: #D
	a: disallowed: 1
}

err: t2: {
	#S: { { c: d: 1 } }
	V: #S
	V: { c: e:  1 }
}

err: t3: p1: {
	#D: {}
	a: #D
	a: c: "C"
}

err: t3: p2: {
	#D: b: {}
	a: #D
	a: b: c: "C"
}

err: t4: {
	a: #A
	#A: b: f: 1
	a: b: h: 1
}

err: t5: {
	// TODO: this should fail
	a: {#A, #B}
	#A: b: f: 1
	#B: b: g: 1
	b: a
	b: b: h: 1 // only an error here
}

err: t6: {
	// TODO: this should fail
	a: {#A, #B}
	#A: b: c: d: e: f: 1
	#B: b: c: d: e: g: 1
	b: a
	b: b: c: d: e: h: 1 // only an error here
}

// TODO: move this test to "ok": _ means any and implicitly defines all fields
// to be present as optional fields with _, recursively (as long as the type
// has not been picked to be non-struct).
// This was not observed in V2, but is now observed in V3. We should probably
// either allow for an error variant that only "allows" all fields but does not
// define them as optional top, or rethink the closedness model altogether.
err: t7: {
	#D: _ & {a: 2}
	a: #D
	a: b: 1
}

err: t8: {
	// nested embedding
	#S: { { c: d: 1 } }
	V: #S
	V: { c: e:  1 } // Should fail
}
-- validators.cue --
import "struct"

// Validators represent top, but in the case of some validators, we should not
// allow a struct to "close" it. Basically, we any validator that takes a
// schema as argument (is marked as NonConcrete) will open up the struct.
//
// TODO: we should aim to eliminate this discrepancy in the closedness redesign.
validator: open: {
	#Schema: {
		matchN(1, [#x])
		#x: trailingComma?: "all"
	}
	data: trailingComma: "all"
	data: #Schema
}

validator: keepClosed: {
	#X: {
		struct.MaxFields(1)
		a?: int
		b?: int
	}
	x: #X
	x: c: 1
}
-- issue1830.cue --
issue1830: {
	#x: {
		y: {
			z?: {
				name: string
			}
		}
	}

	egs: {
		x1: (#x & {y: z: _}).y.z & {
			name: "blah"
			age1: 5
		}
		x2: (#x.y & {z: _}).z & {
			name: "blah"
			age2: 5
		}
	}
}
-- issue3491.cue --
issue3491: {
	#Schema: field?: {}
  
	a: #Schema & {
	  field: {}
	}
  
	a: b
	b: #Extra: {}
}
-- out/evalalpha/stats --
Leaks:  244
Freed:  0
Reused: 0
Allocs: 244
Retain: 0

Unifications: 241
Conjuncts:    428
Disjuncts:    0

CloseIDElems: 1332
NumCloseIDs: 140
-- diff/-out/evalalpha/stats<==>+out/eval/stats --
diff old new
--- old
+++ new
@@ -1,9 +1,12 @@
-Leaks:  5
-Freed:  239
-Reused: 232
-Allocs: 12
-Retain: 25
-
-Unifications: 244
-Conjuncts:    441
-Disjuncts:    263
+Leaks:  244
+Freed:  0
+Reused: 0
+Allocs: 244
+Retain: 0
+
+Unifications: 241
+Conjuncts:    428
+Disjuncts:    0
+
+CloseIDElems: 1332
+NumCloseIDs: 140
-- out/eval/stats --
Leaks:  5
Freed:  239
Reused: 232
Allocs: 12
Retain: 25

Unifications: 244
Conjuncts:    441
Disjuncts:    263
-- out/evalalpha --
Errors:
err.t1.a.disallowed: field not allowed:
    ./in.cue:135:5
err.t2.V.c.e: field not allowed:
    ./in.cue:141:10
err.t3.p1.a.c: field not allowed:
    ./in.cue:147:5
err.t3.p2.a.b.c: field not allowed:
    ./in.cue:153:8
err.t4.a.b.h: field not allowed:
    ./in.cue:159:8
err.t5.b.b.h: field not allowed:
    ./in.cue:168:8
err.t6.b.b.c.d.e.h: field not allowed:
    ./in.cue:177:17
err.t7.a.b: field not allowed:
    ./in.cue:189:5
err.t8.V.c.e: field not allowed:
    ./in.cue:196:10
ok.t13.x.c: field not allowed:
    ./in.cue:112:5
ok.t5.x.c: field not allowed:
    ./in.cue:41:5
validator.keepClosed.x.c: field not allowed:
    ./validators.cue:24:5

Result:
(_|_){
  // [eval]
  ok: (_|_){
    // [eval]
    t1: (struct){
      c: (#list){
        0: (#struct){
          b: (int){ int }
        }
      }
      #R: (list){
      }
    }
    t2: (struct){
      #A: (_){ _ }
      l: (#struct){
        f: (string){ "hi" }
      }
    }
    t3: (struct){
      #A: (#struct){
        f: (#struct){
        }
      }
      #A1: (#struct){
        f: (#struct){
        }
      }
      s: (struct){
        foo: (#struct){
          f: (#struct){
            d: (struct){
              foo: (int){ 1 }
            }
          }
        }
      }
    }
    t4: (struct){
      #T: (#struct){
        a: (#struct){
          b: (int){ 1 }
        }
      }
      W: (#struct){
        b: (struct){
          c: (int){ 2 }
        }
        a: (#struct){
          b: (int){ 1 }
        }
      }
    }
    t5: (_|_){
      // [eval]
      #A: (#struct){
      }
      Common: (struct){
      }
      x: (_|_){
        // [eval]
        c: (_|_){
          // [eval] ok.t5.x.c: field not allowed:
          //     ./in.cue:41:5
        }
      }
    }
    t6: (struct){
      #A: (#struct){
      }
      Common: (struct){
      }
      x: (#struct){
        c: (int){ int }
      }
    }
    t7: (struct){
      a: (#struct){
        b: (#struct){
          f: (int){ 1 }
          g: (int){ 1 }
        }
      }
      #A: (#struct){
        b: (#struct){
          f: (int){ 1 }
        }
      }
      #B: (#struct){
        b: (#struct){
          g: (int){ 1 }
        }
      }
    }
    t8: (struct){
      foo: ~(ok.t8.#X)
      #X: (#struct){
        a: (#struct){
          b: (#struct){
            c: (#struct){
              C: (int){ 1 }
              D: (int){ 2 }
            }
          }
        }
      }
    }
    t9: (struct){
      c: (#list){
        0: (#struct){
          b: (int){ int }
        }
      }
      #R: (list){
      }
    }
    t10: (struct){
      #A: (_){ _ }
      l: (#struct){
        f: (string){ "hi" }
      }
    }
    t11: (struct){
      #A: (#struct){
        f: (#struct){
        }
      }
      #A1: (#struct){
        f: (#struct){
        }
      }
      s: (struct){
        foo: (#struct){
          f: (#struct){
            d: (struct){
              foo: (string){ "bar" }
            }
          }
        }
      }
    }
    t12: (struct){
      #T: (#struct){
        a: (#struct){
          b: (int){ 1 }
        }
      }
      W: (#struct){
        b: (struct){
          c: (int){ 2 }
        }
        a: (#struct){
          b: (int){ 1 }
        }
      }
    }
    t13: (_|_){
      // [eval]
      #A: (#struct){
      }
      Common: (struct){
      }
      x: (_|_){
        // [eval]
        c: (_|_){
          // [eval] ok.t13.x.c: field not allowed:
          //     ./in.cue:112:5
        }
      }
    }
    t14: (struct){
      #A: (#struct){
      }
      Common: (struct){
      }
      x: (#struct){
        c: (int){ int }
      }
    }
  }
  err: (_|_){
    // [eval]
    t1: (_|_){
      // [eval]
      #D: (#struct){
        a: (int){ 2 }
      }
      a: (_|_){
        // [eval]
        disallowed: (_|_){
          // [eval] err.t1.a.disallowed: field not allowed:
          //     ./in.cue:135:5
        }
        a: (int){ 2 }
      }
    }
    t2: (_|_){
      // [eval]
      #S: (#struct){
        c: (#struct){
          d: (int){ 1 }
        }
      }
      V: (_|_){
        // [eval]
        c: (_|_){
          // [eval]
          e: (_|_){
            // [eval] err.t2.V.c.e: field not allowed:
            //     ./in.cue:141:10
          }
          d: (int){ 1 }
        }
      }
    }
    t3: (_|_){
      // [eval]
      p1: (_|_){
        // [eval]
        #D: (#struct){
        }
        a: (_|_){
          // [eval]
          c: (_|_){
            // [eval] err.t3.p1.a.c: field not allowed:
            //     ./in.cue:147:5
          }
        }
      }
      p2: (_|_){
        // [eval]
        #D: (#struct){
          b: (#struct){
          }
        }
        a: (_|_){
          // [eval]
          b: (_|_){
            // [eval]
            c: (_|_){
              // [eval] err.t3.p2.a.b.c: field not allowed:
              //     ./in.cue:153:8
            }
          }
        }
      }
    }
    t4: (_|_){
      // [eval]
      a: (_|_){
        // [eval]
        b: (_|_){
          // [eval]
          h: (_|_){
            // [eval] err.t4.a.b.h: field not allowed:
            //     ./in.cue:159:8
          }
          f: (int){ 1 }
        }
      }
      #A: (#struct){
        b: (#struct){
          f: (int){ 1 }
        }
      }
    }
    t5: (_|_){
      // [eval]
      a: (#struct){
        b: (#struct){
          f: (int){ 1 }
          g: (int){ 1 }
        }
      }
      #A: (#struct){
        b: (#struct){
          f: (int){ 1 }
        }
      }
      #B: (#struct){
        b: (#struct){
          g: (int){ 1 }
        }
      }
      b: (_|_){
        // [eval]
        b: (_|_){
          // [eval]
          h: (_|_){
            // [eval] err.t5.b.b.h: field not allowed:
            //     ./in.cue:168:8
          }
          f: (int){ 1 }
          g: (int){ 1 }
        }
      }
    }
    t6: (_|_){
      // [eval]
      a: (#struct){
        b: (#struct){
          c: (#struct){
            d: (#struct){
              e: (#struct){
                f: (int){ 1 }
                g: (int){ 1 }
              }
            }
          }
        }
      }
      #A: (#struct){
        b: (#struct){
          c: (#struct){
            d: (#struct){
              e: (#struct){
                f: (int){ 1 }
              }
            }
          }
        }
      }
      #B: (#struct){
        b: (#struct){
          c: (#struct){
            d: (#struct){
              e: (#struct){
                g: (int){ 1 }
              }
            }
          }
        }
      }
      b: (_|_){
        // [eval]
        b: (_|_){
          // [eval]
          c: (_|_){
            // [eval]
            d: (_|_){
              // [eval]
              e: (_|_){
                // [eval]
                h: (_|_){
                  // [eval] err.t6.b.b.c.d.e.h: field not allowed:
                  //     ./in.cue:177:17
                }
                f: (int){ 1 }
                g: (int){ 1 }
              }
            }
          }
        }
      }
    }
    t7: (_|_){
      // [eval]
      #D: (#struct){
        a: (int){ 2 }
      }
      a: (_|_){
        // [eval]
        b: (_|_){
          // [eval] err.t7.a.b: field not allowed:
          //     ./in.cue:189:5
        }
        a: (int){ 2 }
      }
    }
    t8: (_|_){
      // [eval]
      #S: (#struct){
        c: (#struct){
          d: (int){ 1 }
        }
      }
      V: (_|_){
        // [eval]
        c: (_|_){
          // [eval]
          e: (_|_){
            // [eval] err.t8.V.c.e: field not allowed:
            //     ./in.cue:196:10
          }
          d: (int){ 1 }
        }
      }
    }
  }
  issue1830: (struct){
    #x: (#struct){
      y: (#struct){
        z?: (#struct){
          name: (string){ string }
        }
      }
    }
    egs: (struct){
      x1: (#struct){
        name: (string){ "blah" }
        age1: (int){ 5 }
      }
      x2: (#struct){
        name: (string){ "blah" }
        age2: (int){ 5 }
      }
    }
  }
  issue3491: (struct){
    #Schema: (#struct){
      field?: (#struct){
      }
    }
    a: (#struct){
      field: (#struct){
      }
      #Extra: (#struct){
      }
    }
    b: (struct){
      #Extra: (#struct){
      }
    }
  }
  validator: (_|_){
    // [eval]
    open: (struct){
      #Schema: (_){
        matchN(1, (#list){
          0: (_|_){// 〈1;#x〉
          }
        })
        #x: (#struct){
          trailingComma?: (string){ "all" }
        }
      }
      data: (#struct){
        trailingComma: (string){ "all" }
        #x: (#struct){
          trailingComma?: (string){ "all" }
        }
      }
    }
    keepClosed: (_|_){
      // [eval]
      #X: (#struct){
        a?: (int){ int }
        b?: (int){ int }
      }
      x: (_|_){
        // [eval]
        c: (_|_){
          // [eval] validator.keepClosed.x.c: field not allowed:
          //     ./validators.cue:24:5
        }
        a?: (int){ int }
        b?: (int){ int }
      }
    }
  }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -1,74 +1,28 @@
 Errors:
 err.t1.a.disallowed: field not allowed:
-    ./in.cue:133:10
-    ./in.cue:134:5
     ./in.cue:135:5
 err.t2.V.c.e: field not allowed:
-    ./in.cue:139:8
-    ./in.cue:139:13
-    ./in.cue:140:5
     ./in.cue:141:10
 err.t3.p1.a.c: field not allowed:
-    ./in.cue:145:6
-    ./in.cue:146:5
     ./in.cue:147:5
 err.t3.p2.a.b.c: field not allowed:
-    ./in.cue:151:9
-    ./in.cue:152:5
     ./in.cue:153:8
 err.t4.a.b.h: field not allowed:
-    ./in.cue:157:5
-    ./in.cue:158:9
     ./in.cue:159:8
 err.t5.b.b.h: field not allowed:
-    ./in.cue:164:6
-    ./in.cue:164:10
-    ./in.cue:165:9
-    ./in.cue:166:9
-    ./in.cue:167:5
     ./in.cue:168:8
 err.t6.b.b.c.d.e.h: field not allowed:
-    ./in.cue:173:6
-    ./in.cue:173:10
-    ./in.cue:174:18
-    ./in.cue:175:18
-    ./in.cue:176:5
     ./in.cue:177:17
 err.t7.a.b: field not allowed:
-    ./in.cue:187:10
-    ./in.cue:188:5
     ./in.cue:189:5
 err.t8.V.c.e: field not allowed:
-    ./in.cue:194:8
-    ./in.cue:194:13
-    ./in.cue:195:5
     ./in.cue:196:10
 ok.t13.x.c: field not allowed:
-    ./in.cue:106:6
-    ./in.cue:107:3
-    ./in.cue:110:10
-    ./in.cue:111:5
     ./in.cue:112:5
 ok.t5.x.c: field not allowed:
-    ./in.cue:35:6
-    ./in.cue:36:3
-    ./in.cue:39:10
-    ./in.cue:40:5
     ./in.cue:41:5
 validator.keepClosed.x.c: field not allowed:
-    ./validators.cue:18:6
-    ./validators.cue:23:5
     ./validators.cue:24:5
-validator.open.data: invalid value {trailingComma:_|_(validator.open.data.trailingComma: field not allowed),#x:{trailingComma?:"all"}} (does not satisfy matchN): 0 matched, expected 1:
-    ./validators.cue:10:3
-    ./validators.cue:10:10
-    ./validators.cue:13:8
-    ./validators.cue:14:8
-validator.open.data.trailingComma: field not allowed:
-    ./validators.cue:10:3
-    ./validators.cue:9:11
-    ./validators.cue:13:8
-    ./validators.cue:14:8
 
 Result:
 (_|_){
@@ -77,7 +31,7 @@
     // [eval]
     t1: (struct){
       c: (#list){
-        0: (struct){
+        0: (#struct){
           b: (int){ int }
         }
       }
@@ -86,7 +40,7 @@
     }
     t2: (struct){
       #A: (_){ _ }
-      l: (struct){
+      l: (#struct){
         f: (string){ "hi" }
       }
     }
@@ -116,11 +70,11 @@
         }
       }
       W: (#struct){
-        a: (#struct){
-          b: (int){ 1 }
-        }
-        b: (struct){
-          c: (int){ 2 }
+        b: (struct){
+          c: (int){ 2 }
+        }
+        a: (#struct){
+          b: (int){ 1 }
         }
       }
     }
@@ -134,10 +88,6 @@
         // [eval]
         c: (_|_){
           // [eval] ok.t5.x.c: field not allowed:
-          //     ./in.cue:35:6
-          //     ./in.cue:36:3
-          //     ./in.cue:39:10
-          //     ./in.cue:40:5
           //     ./in.cue:41:5
         }
       }
@@ -170,16 +120,7 @@
       }
     }
     t8: (struct){
-      foo: (#struct){
-        a: (#struct){
-          b: (#struct){
-            c: (#struct){
-              C: (int){ 1 }
-              D: (int){ 2 }
-            }
-          }
-        }
-      }
+      foo: ~(ok.t8.#X)
       #X: (#struct){
         a: (#struct){
           b: (#struct){
@@ -193,7 +134,7 @@
     }
     t9: (struct){
       c: (#list){
-        0: (struct){
+        0: (#struct){
           b: (int){ int }
         }
       }
@@ -202,7 +143,7 @@
     }
     t10: (struct){
       #A: (_){ _ }
-      l: (struct){
+      l: (#struct){
         f: (string){ "hi" }
       }
     }
@@ -232,11 +173,11 @@
         }
       }
       W: (#struct){
-        a: (#struct){
-          b: (int){ 1 }
-        }
-        b: (struct){
-          c: (int){ 2 }
+        b: (struct){
+          c: (int){ 2 }
+        }
+        a: (#struct){
+          b: (int){ 1 }
         }
       }
     }
@@ -250,10 +191,6 @@
         // [eval]
         c: (_|_){
           // [eval] ok.t13.x.c: field not allowed:
-          //     ./in.cue:106:6
-          //     ./in.cue:107:3
-          //     ./in.cue:110:10
-          //     ./in.cue:111:5
           //     ./in.cue:112:5
         }
       }
@@ -277,13 +214,11 @@
       }
       a: (_|_){
         // [eval]
-        a: (int){ 2 }
         disallowed: (_|_){
           // [eval] err.t1.a.disallowed: field not allowed:
-          //     ./in.cue:133:10
-          //     ./in.cue:134:5
           //     ./in.cue:135:5
         }
+        a: (int){ 2 }
       }
     }
     t2: (_|_){
@@ -297,14 +232,11 @@
         // [eval]
         c: (_|_){
           // [eval]
-          d: (int){ 1 }
           e: (_|_){
             // [eval] err.t2.V.c.e: field not allowed:
-            //     ./in.cue:139:8
-            //     ./in.cue:139:13
-            //     ./in.cue:140:5
             //     ./in.cue:141:10
           }
+          d: (int){ 1 }
         }
       }
     }
@@ -318,8 +250,6 @@
           // [eval]
           c: (_|_){
             // [eval] err.t3.p1.a.c: field not allowed:
-            //     ./in.cue:145:6
-            //     ./in.cue:146:5
             //     ./in.cue:147:5
           }
         }
@@ -336,8 +266,6 @@
             // [eval]
             c: (_|_){
               // [eval] err.t3.p2.a.b.c: field not allowed:
-              //     ./in.cue:151:9
-              //     ./in.cue:152:5
               //     ./in.cue:153:8
             }
           }
@@ -350,54 +278,47 @@
         // [eval]
         b: (_|_){
           // [eval]
-          f: (int){ 1 }
           h: (_|_){
             // [eval] err.t4.a.b.h: field not allowed:
-            //     ./in.cue:157:5
-            //     ./in.cue:158:9
             //     ./in.cue:159:8
           }
-        }
-      }
-      #A: (#struct){
-        b: (#struct){
-          f: (int){ 1 }
-        }
-      }
-    }
-    t5: (_|_){
-      // [eval]
-      a: (#struct){
-        b: (#struct){
-          f: (int){ 1 }
-          g: (int){ 1 }
-        }
-      }
-      #A: (#struct){
-        b: (#struct){
-          f: (int){ 1 }
-        }
-      }
-      #B: (#struct){
-        b: (#struct){
-          g: (int){ 1 }
-        }
-      }
-      b: (_|_){
-        // [eval]
-        b: (_|_){
-          // [eval]
-          f: (int){ 1 }
-          g: (int){ 1 }
+          f: (int){ 1 }
+        }
+      }
+      #A: (#struct){
+        b: (#struct){
+          f: (int){ 1 }
+        }
+      }
+    }
+    t5: (_|_){
+      // [eval]
+      a: (#struct){
+        b: (#struct){
+          f: (int){ 1 }
+          g: (int){ 1 }
+        }
+      }
+      #A: (#struct){
+        b: (#struct){
+          f: (int){ 1 }
+        }
+      }
+      #B: (#struct){
+        b: (#struct){
+          g: (int){ 1 }
+        }
+      }
+      b: (_|_){
+        // [eval]
+        b: (_|_){
+          // [eval]
           h: (_|_){
             // [eval] err.t5.b.b.h: field not allowed:
-            //     ./in.cue:164:6
-            //     ./in.cue:164:10
-            //     ./in.cue:165:9
-            //     ./in.cue:166:9
-            //     ./in.cue:167:5
             //     ./in.cue:168:8
           }
+          f: (int){ 1 }
+          g: (int){ 1 }
         }
       }
     }
@@ -447,17 +368,12 @@
               // [eval]
               e: (_|_){
                 // [eval]
-                f: (int){ 1 }
-                g: (int){ 1 }
                 h: (_|_){
                   // [eval] err.t6.b.b.c.d.e.h: field not allowed:
-                  //     ./in.cue:173:6
-                  //     ./in.cue:173:10
-                  //     ./in.cue:174:18
-                  //     ./in.cue:175:18
-                  //     ./in.cue:176:5
                   //     ./in.cue:177:17
                 }
+                f: (int){ 1 }
+                g: (int){ 1 }
               }
             }
           }
@@ -471,13 +387,11 @@
       }
       a: (_|_){
         // [eval]
-        a: (int){ 2 }
         b: (_|_){
           // [eval] err.t7.a.b: field not allowed:
-          //     ./in.cue:187:10
-          //     ./in.cue:188:5
           //     ./in.cue:189:5
         }
+        a: (int){ 2 }
       }
     }
     t8: (_|_){
@@ -491,14 +405,11 @@
         // [eval]
         c: (_|_){
           // [eval]
-          d: (int){ 1 }
           e: (_|_){
             // [eval] err.t8.V.c.e: field not allowed:
-            //     ./in.cue:194:8
-            //     ./in.cue:194:13
-            //     ./in.cue:195:5
             //     ./in.cue:196:10
           }
+          d: (int){ 1 }
         }
       }
     }
@@ -512,11 +423,11 @@
       }
     }
     egs: (struct){
-      x1: (struct){
+      x1: (#struct){
         name: (string){ "blah" }
         age1: (int){ 5 }
       }
-      x2: (struct){
+      x2: (#struct){
         name: (string){ "blah" }
         age2: (int){ 5 }
       }
@@ -540,8 +451,7 @@
   }
   validator: (_|_){
     // [eval]
-    open: (_|_){
-      // [eval]
+    open: (struct){
       #Schema: (_){
         matchN(1, (#list){
           0: (_|_){// 〈1;#x〉
@@ -551,28 +461,10 @@
           trailingComma?: (string){ "all" }
         }
       }
-      data: (_|_){
-        // [eval] validator.open.data: invalid value {trailingComma:_|_(validator.open.data.trailingComma: field not allowed),#x:{trailingComma?:"all"}} (does not satisfy matchN): 0 matched, expected 1:
-        //     ./validators.cue:10:3
-        //     ./validators.cue:10:10
-        //     ./validators.cue:13:8
-        //     ./validators.cue:14:8
-        // validator.open.data.trailingComma: field not allowed:
-        //     ./validators.cue:10:3
-        //     ./validators.cue:9:11
-        //     ./validators.cue:13:8
-        //     ./validators.cue:14:8
-        trailingComma: (_|_){
-          // [eval] validator.open.data.trailingComma: field not allowed:
-          //     ./validators.cue:10:3
-          //     ./validators.cue:9:11
-          //     ./validators.cue:13:8
-          //     ./validators.cue:14:8
-        }
-        #x: (_|_){
-          // [eval]
-          trailingComma?: (_|_){// "all"
-          }
+      data: (#struct){
+        trailingComma: (string){ "all" }
+        #x: (#struct){
+          trailingComma?: (string){ "all" }
         }
       }
     }
@@ -584,14 +476,12 @@
       }
       x: (_|_){
         // [eval]
-        a?: (int){ int }
-        b?: (int){ int }
         c: (_|_){
           // [eval] validator.keepClosed.x.c: field not allowed:
-          //     ./validators.cue:18:6
-          //     ./validators.cue:23:5
           //     ./validators.cue:24:5
         }
+        a?: (int){ int }
+        b?: (int){ int }
       }
     }
   }
-- diff/todo/p2 --
all: error positions and reordering.
-- diff/explanation --
issue1830: the new evaluator correctly rejects inserting new fields in a closed struct
err.t(1|2): bug fixes.
-- out/eval --
Errors:
err.t1.a.disallowed: field not allowed:
    ./in.cue:133:10
    ./in.cue:134:5
    ./in.cue:135:5
err.t2.V.c.e: field not allowed:
    ./in.cue:139:8
    ./in.cue:139:13
    ./in.cue:140:5
    ./in.cue:141:10
err.t3.p1.a.c: field not allowed:
    ./in.cue:145:6
    ./in.cue:146:5
    ./in.cue:147:5
err.t3.p2.a.b.c: field not allowed:
    ./in.cue:151:9
    ./in.cue:152:5
    ./in.cue:153:8
err.t4.a.b.h: field not allowed:
    ./in.cue:157:5
    ./in.cue:158:9
    ./in.cue:159:8
err.t5.b.b.h: field not allowed:
    ./in.cue:164:6
    ./in.cue:164:10
    ./in.cue:165:9
    ./in.cue:166:9
    ./in.cue:167:5
    ./in.cue:168:8
err.t6.b.b.c.d.e.h: field not allowed:
    ./in.cue:173:6
    ./in.cue:173:10
    ./in.cue:174:18
    ./in.cue:175:18
    ./in.cue:176:5
    ./in.cue:177:17
err.t7.a.b: field not allowed:
    ./in.cue:187:10
    ./in.cue:188:5
    ./in.cue:189:5
err.t8.V.c.e: field not allowed:
    ./in.cue:194:8
    ./in.cue:194:13
    ./in.cue:195:5
    ./in.cue:196:10
ok.t13.x.c: field not allowed:
    ./in.cue:106:6
    ./in.cue:107:3
    ./in.cue:110:10
    ./in.cue:111:5
    ./in.cue:112:5
ok.t5.x.c: field not allowed:
    ./in.cue:35:6
    ./in.cue:36:3
    ./in.cue:39:10
    ./in.cue:40:5
    ./in.cue:41:5
validator.keepClosed.x.c: field not allowed:
    ./validators.cue:18:6
    ./validators.cue:23:5
    ./validators.cue:24:5
validator.open.data: invalid value {trailingComma:_|_(validator.open.data.trailingComma: field not allowed),#x:{trailingComma?:"all"}} (does not satisfy matchN): 0 matched, expected 1:
    ./validators.cue:10:3
    ./validators.cue:10:10
    ./validators.cue:13:8
    ./validators.cue:14:8
validator.open.data.trailingComma: field not allowed:
    ./validators.cue:10:3
    ./validators.cue:9:11
    ./validators.cue:13:8
    ./validators.cue:14:8

Result:
(_|_){
  // [eval]
  ok: (_|_){
    // [eval]
    t1: (struct){
      c: (#list){
        0: (struct){
          b: (int){ int }
        }
      }
      #R: (list){
      }
    }
    t2: (struct){
      #A: (_){ _ }
      l: (struct){
        f: (string){ "hi" }
      }
    }
    t3: (struct){
      #A: (#struct){
        f: (#struct){
        }
      }
      #A1: (#struct){
        f: (#struct){
        }
      }
      s: (struct){
        foo: (#struct){
          f: (#struct){
            d: (struct){
              foo: (int){ 1 }
            }
          }
        }
      }
    }
    t4: (struct){
      #T: (#struct){
        a: (#struct){
          b: (int){ 1 }
        }
      }
      W: (#struct){
        a: (#struct){
          b: (int){ 1 }
        }
        b: (struct){
          c: (int){ 2 }
        }
      }
    }
    t5: (_|_){
      // [eval]
      #A: (#struct){
      }
      Common: (struct){
      }
      x: (_|_){
        // [eval]
        c: (_|_){
          // [eval] ok.t5.x.c: field not allowed:
          //     ./in.cue:35:6
          //     ./in.cue:36:3
          //     ./in.cue:39:10
          //     ./in.cue:40:5
          //     ./in.cue:41:5
        }
      }
    }
    t6: (struct){
      #A: (#struct){
      }
      Common: (struct){
      }
      x: (#struct){
        c: (int){ int }
      }
    }
    t7: (struct){
      a: (#struct){
        b: (#struct){
          f: (int){ 1 }
          g: (int){ 1 }
        }
      }
      #A: (#struct){
        b: (#struct){
          f: (int){ 1 }
        }
      }
      #B: (#struct){
        b: (#struct){
          g: (int){ 1 }
        }
      }
    }
    t8: (struct){
      foo: (#struct){
        a: (#struct){
          b: (#struct){
            c: (#struct){
              C: (int){ 1 }
              D: (int){ 2 }
            }
          }
        }
      }
      #X: (#struct){
        a: (#struct){
          b: (#struct){
            c: (#struct){
              C: (int){ 1 }
              D: (int){ 2 }
            }
          }
        }
      }
    }
    t9: (struct){
      c: (#list){
        0: (struct){
          b: (int){ int }
        }
      }
      #R: (list){
      }
    }
    t10: (struct){
      #A: (_){ _ }
      l: (struct){
        f: (string){ "hi" }
      }
    }
    t11: (struct){
      #A: (#struct){
        f: (#struct){
        }
      }
      #A1: (#struct){
        f: (#struct){
        }
      }
      s: (struct){
        foo: (#struct){
          f: (#struct){
            d: (struct){
              foo: (string){ "bar" }
            }
          }
        }
      }
    }
    t12: (struct){
      #T: (#struct){
        a: (#struct){
          b: (int){ 1 }
        }
      }
      W: (#struct){
        a: (#struct){
          b: (int){ 1 }
        }
        b: (struct){
          c: (int){ 2 }
        }
      }
    }
    t13: (_|_){
      // [eval]
      #A: (#struct){
      }
      Common: (struct){
      }
      x: (_|_){
        // [eval]
        c: (_|_){
          // [eval] ok.t13.x.c: field not allowed:
          //     ./in.cue:106:6
          //     ./in.cue:107:3
          //     ./in.cue:110:10
          //     ./in.cue:111:5
          //     ./in.cue:112:5
        }
      }
    }
    t14: (struct){
      #A: (#struct){
      }
      Common: (struct){
      }
      x: (#struct){
        c: (int){ int }
      }
    }
  }
  err: (_|_){
    // [eval]
    t1: (_|_){
      // [eval]
      #D: (#struct){
        a: (int){ 2 }
      }
      a: (_|_){
        // [eval]
        a: (int){ 2 }
        disallowed: (_|_){
          // [eval] err.t1.a.disallowed: field not allowed:
          //     ./in.cue:133:10
          //     ./in.cue:134:5
          //     ./in.cue:135:5
        }
      }
    }
    t2: (_|_){
      // [eval]
      #S: (#struct){
        c: (#struct){
          d: (int){ 1 }
        }
      }
      V: (_|_){
        // [eval]
        c: (_|_){
          // [eval]
          d: (int){ 1 }
          e: (_|_){
            // [eval] err.t2.V.c.e: field not allowed:
            //     ./in.cue:139:8
            //     ./in.cue:139:13
            //     ./in.cue:140:5
            //     ./in.cue:141:10
          }
        }
      }
    }
    t3: (_|_){
      // [eval]
      p1: (_|_){
        // [eval]
        #D: (#struct){
        }
        a: (_|_){
          // [eval]
          c: (_|_){
            // [eval] err.t3.p1.a.c: field not allowed:
            //     ./in.cue:145:6
            //     ./in.cue:146:5
            //     ./in.cue:147:5
          }
        }
      }
      p2: (_|_){
        // [eval]
        #D: (#struct){
          b: (#struct){
          }
        }
        a: (_|_){
          // [eval]
          b: (_|_){
            // [eval]
            c: (_|_){
              // [eval] err.t3.p2.a.b.c: field not allowed:
              //     ./in.cue:151:9
              //     ./in.cue:152:5
              //     ./in.cue:153:8
            }
          }
        }
      }
    }
    t4: (_|_){
      // [eval]
      a: (_|_){
        // [eval]
        b: (_|_){
          // [eval]
          f: (int){ 1 }
          h: (_|_){
            // [eval] err.t4.a.b.h: field not allowed:
            //     ./in.cue:157:5
            //     ./in.cue:158:9
            //     ./in.cue:159:8
          }
        }
      }
      #A: (#struct){
        b: (#struct){
          f: (int){ 1 }
        }
      }
    }
    t5: (_|_){
      // [eval]
      a: (#struct){
        b: (#struct){
          f: (int){ 1 }
          g: (int){ 1 }
        }
      }
      #A: (#struct){
        b: (#struct){
          f: (int){ 1 }
        }
      }
      #B: (#struct){
        b: (#struct){
          g: (int){ 1 }
        }
      }
      b: (_|_){
        // [eval]
        b: (_|_){
          // [eval]
          f: (int){ 1 }
          g: (int){ 1 }
          h: (_|_){
            // [eval] err.t5.b.b.h: field not allowed:
            //     ./in.cue:164:6
            //     ./in.cue:164:10
            //     ./in.cue:165:9
            //     ./in.cue:166:9
            //     ./in.cue:167:5
            //     ./in.cue:168:8
          }
        }
      }
    }
    t6: (_|_){
      // [eval]
      a: (#struct){
        b: (#struct){
          c: (#struct){
            d: (#struct){
              e: (#struct){
                f: (int){ 1 }
                g: (int){ 1 }
              }
            }
          }
        }
      }
      #A: (#struct){
        b: (#struct){
          c: (#struct){
            d: (#struct){
              e: (#struct){
                f: (int){ 1 }
              }
            }
          }
        }
      }
      #B: (#struct){
        b: (#struct){
          c: (#struct){
            d: (#struct){
              e: (#struct){
                g: (int){ 1 }
              }
            }
          }
        }
      }
      b: (_|_){
        // [eval]
        b: (_|_){
          // [eval]
          c: (_|_){
            // [eval]
            d: (_|_){
              // [eval]
              e: (_|_){
                // [eval]
                f: (int){ 1 }
                g: (int){ 1 }
                h: (_|_){
                  // [eval] err.t6.b.b.c.d.e.h: field not allowed:
                  //     ./in.cue:173:6
                  //     ./in.cue:173:10
                  //     ./in.cue:174:18
                  //     ./in.cue:175:18
                  //     ./in.cue:176:5
                  //     ./in.cue:177:17
                }
              }
            }
          }
        }
      }
    }
    t7: (_|_){
      // [eval]
      #D: (#struct){
        a: (int){ 2 }
      }
      a: (_|_){
        // [eval]
        a: (int){ 2 }
        b: (_|_){
          // [eval] err.t7.a.b: field not allowed:
          //     ./in.cue:187:10
          //     ./in.cue:188:5
          //     ./in.cue:189:5
        }
      }
    }
    t8: (_|_){
      // [eval]
      #S: (#struct){
        c: (#struct){
          d: (int){ 1 }
        }
      }
      V: (_|_){
        // [eval]
        c: (_|_){
          // [eval]
          d: (int){ 1 }
          e: (_|_){
            // [eval] err.t8.V.c.e: field not allowed:
            //     ./in.cue:194:8
            //     ./in.cue:194:13
            //     ./in.cue:195:5
            //     ./in.cue:196:10
          }
        }
      }
    }
  }
  issue1830: (struct){
    #x: (#struct){
      y: (#struct){
        z?: (#struct){
          name: (string){ string }
        }
      }
    }
    egs: (struct){
      x1: (struct){
        name: (string){ "blah" }
        age1: (int){ 5 }
      }
      x2: (struct){
        name: (string){ "blah" }
        age2: (int){ 5 }
      }
    }
  }
  issue3491: (struct){
    #Schema: (#struct){
      field?: (#struct){
      }
    }
    a: (#struct){
      field: (#struct){
      }
      #Extra: (#struct){
      }
    }
    b: (struct){
      #Extra: (#struct){
      }
    }
  }
  validator: (_|_){
    // [eval]
    open: (_|_){
      // [eval]
      #Schema: (_){
        matchN(1, (#list){
          0: (_|_){// 〈1;#x〉
          }
        })
        #x: (#struct){
          trailingComma?: (string){ "all" }
        }
      }
      data: (_|_){
        // [eval] validator.open.data: invalid value {trailingComma:_|_(validator.open.data.trailingComma: field not allowed),#x:{trailingComma?:"all"}} (does not satisfy matchN): 0 matched, expected 1:
        //     ./validators.cue:10:3
        //     ./validators.cue:10:10
        //     ./validators.cue:13:8
        //     ./validators.cue:14:8
        // validator.open.data.trailingComma: field not allowed:
        //     ./validators.cue:10:3
        //     ./validators.cue:9:11
        //     ./validators.cue:13:8
        //     ./validators.cue:14:8
        trailingComma: (_|_){
          // [eval] validator.open.data.trailingComma: field not allowed:
          //     ./validators.cue:10:3
          //     ./validators.cue:9:11
          //     ./validators.cue:13:8
          //     ./validators.cue:14:8
        }
        #x: (_|_){
          // [eval]
          trailingComma?: (_|_){// "all"
          }
        }
      }
    }
    keepClosed: (_|_){
      // [eval]
      #X: (#struct){
        a?: (int){ int }
        b?: (int){ int }
      }
      x: (_|_){
        // [eval]
        a?: (int){ int }
        b?: (int){ int }
        c: (_|_){
          // [eval] validator.keepClosed.x.c: field not allowed:
          //     ./validators.cue:18:6
          //     ./validators.cue:23:5
          //     ./validators.cue:24:5
        }
      }
    }
  }
}
-- out/compile --
--- in.cue
{
  ok: {
    t1: {
      c: 〈0;#R〉
      c: [
        {
          b: int
        },
      ]
      #R: [
        ...,
      ]
    }
  }
  ok: {
    t2: {
      #A: _
      l: 〈0;#A〉
      l: {
        f: "hi"
      }
    }
  }
  ok: {
    t3: {
      #A: {
        f: {
          ...
        }
      }
      #A1: {
        〈1;#A〉
      }
      s: {
        [string]: 〈1;#A1〉
      }
      s: {
        foo: {
          f: {
            d: {
              foo: 1
            }
          }
        }
      }
    }
  }
  ok: {
    t4: {
      #T: {
        a: {
          b: 1
        }
      }
      W: {
        {
          〈2;#T〉
        }
        b: {
          c: 2
        }
      }
    }
  }
  ok: {
    t5: {
      #A: {
        〈1;Common〉
        _
      }
      Common: {}
      x: 〈0;#A〉
      x: {
        c: int
      }
    }
  }
  ok: {
    t6: {
      #A: {
        〈1;Common〉
        ...
      }
      Common: {}
      x: 〈0;#A〉
      x: {
        c: int
      }
    }
  }
  ok: {
    t7: {
      a: {
        〈1;#A〉
        〈1;#B〉
      }
      #A: {
        b: {
          f: 1
        }
      }
      #B: {
        b: {
          g: 1
        }
      }
    }
  }
  ok: {
    t8: {
      foo: 〈0;#X〉
      #X: {
        a: {
          b: {
            c: {
              C: 1
            }
          }
        }
        for k, _ in 〈0;a〉 {
          a: {
            〈2;k〉: {
              c: {
                D: 2
              }
            }
          }
        }
      }
    }
  }
  ok: {
    t9: {
      c: 〈0;#R〉
      c: [
        {
          b: int
        },
      ]
      #R: [
        ...,
      ]
    }
  }
  ok: {
    t10: {
      #A: _
      l: 〈0;#A〉
      l: {
        f: "hi"
      }
    }
  }
  ok: {
    t11: {
      #A: {
        f: {
          ...
        }
      }
      #A1: {
        〈1;#A〉
      }
      s: {
        [string]: 〈1;#A1〉
      }
      s: {
        foo: {
          f: {
            d: {
              foo: "bar"
            }
          }
        }
      }
    }
  }
  ok: {
    t12: {
      #T: {
        a: {
          b: 1
        }
      }
      W: {
        {
          〈2;#T〉
        }
        b: {
          c: 2
        }
      }
    }
  }
  ok: {
    t13: {
      #A: {
        〈1;Common〉
        _
      }
      Common: {}
      x: 〈0;#A〉
      x: {
        c: int
      }
    }
  }
  ok: {
    t14: {
      #A: {
        〈1;Common〉
        ...
      }
      Common: {}
      x: 〈0;#A〉
      x: {
        c: int
      }
    }
  }
  err: {
    t1: {
      #D: (_ & {
        a: 2
      })
      a: 〈0;#D〉
      a: {
        disallowed: 1
      }
    }
  }
  err: {
    t2: {
      #S: {
        {
          c: {
            d: 1
          }
        }
      }
      V: 〈0;#S〉
      V: {
        c: {
          e: 1
        }
      }
    }
  }
  err: {
    t3: {
      p1: {
        #D: {}
        a: 〈0;#D〉
        a: {
          c: "C"
        }
      }
    }
  }
  err: {
    t3: {
      p2: {
        #D: {
          b: {}
        }
        a: 〈0;#D〉
        a: {
          b: {
            c: "C"
          }
        }
      }
    }
  }
  err: {
    t4: {
      a: 〈0;#A〉
      #A: {
        b: {
          f: 1
        }
      }
      a: {
        b: {
          h: 1
        }
      }
    }
  }
  err: {
    t5: {
      a: {
        〈1;#A〉
        〈1;#B〉
      }
      #A: {
        b: {
          f: 1
        }
      }
      #B: {
        b: {
          g: 1
        }
      }
      b: 〈0;a〉
      b: {
        b: {
          h: 1
        }
      }
    }
  }
  err: {
    t6: {
      a: {
        〈1;#A〉
        〈1;#B〉
      }
      #A: {
        b: {
          c: {
            d: {
              e: {
                f: 1
              }
            }
          }
        }
      }
      #B: {
        b: {
          c: {
            d: {
              e: {
                g: 1
              }
            }
          }
        }
      }
      b: 〈0;a〉
      b: {
        b: {
          c: {
            d: {
              e: {
                h: 1
              }
            }
          }
        }
      }
    }
  }
  err: {
    t7: {
      #D: (_ & {
        a: 2
      })
      a: 〈0;#D〉
      a: {
        b: 1
      }
    }
  }
  err: {
    t8: {
      #S: {
        {
          c: {
            d: 1
          }
        }
      }
      V: 〈0;#S〉
      V: {
        c: {
          e: 1
        }
      }
    }
  }
}
--- issue1830.cue
{
  issue1830: {
    #x: {
      y: {
        z?: {
          name: string
        }
      }
    }
    egs: {
      x1: ((〈1;#x〉 & {
        y: {
          z: _
        }
      }).y.z & {
        name: "blah"
        age1: 5
      })
      x2: ((〈1;#x〉.y & {
        z: _
      }).z & {
        name: "blah"
        age2: 5
      })
    }
  }
}
--- issue3491.cue
{
  issue3491: {
    #Schema: {
      field?: {}
    }
    a: (〈0;#Schema〉 & {
      field: {}
    })
    a: 〈0;b〉
    b: {
      #Extra: {}
    }
  }
}
--- validators.cue
{
  validator: {
    open: {
      #Schema: {
        matchN(1, [
          〈1;#x〉,
        ])
        #x: {
          trailingComma?: "all"
        }
      }
      data: {
        trailingComma: "all"
      }
      data: 〈0;#Schema〉
    }
  }
  validator: {
    keepClosed: {
      #X: {
        〈import;struct〉.MaxFields(1)
        a?: int
        b?: int
      }
      x: 〈0;#X〉
      x: {
        c: 1
      }
    }
  }
}
