-- in.cue --
a: close({
	a: b: int
})

b: a & {x:    int} // err
c: a & {a: c: int} // okay (non-recursive close)

inDisjunctions: {
	x: [string]: #Def
	#Def: [string]: {
		a: b: true
		let X = a
		close({uint: a: b: X.b}) | close({string: a: b: true})
	}
	x: socket: string: {}
	x: syslog: x.socket
	x: syslog: xxx: {}
}

issue642: {
	test: close({
		a: _
		b: x: _
	} & {
		[string]: y: _
	})

	test: a: x: _
	test: b: x: _
}

// Issue 642
withSubfields: {
	test: close({
		a: _
		b: x:        _
		[string]: y: _
	})

	test: a: x: _
	test: b: x: _
}

issue3572: {
  t1: close({...}) & {a: 5}

  e: close({...})

  t2: e & {a: 5}
}

issue3580: {
	x: close({
		a: _
		b: x.a
	})
}
-- out/evalalpha/stats --
Leaks:  378
Freed:  0
Reused: 0
Allocs: 378
Retain: 0

Unifications: 179
Conjuncts:    595
Disjuncts:    24
-- diff/-out/evalalpha/stats<==>+out/eval/stats --
diff old new
--- old
+++ new
@@ -1,9 +1,9 @@
-Leaks:  43
-Freed:  170
-Reused: 164
-Allocs: 49
-Retain: 44
+Leaks:  378
+Freed:  0
+Reused: 0
+Allocs: 378
+Retain: 0
 
-Unifications: 199
-Conjuncts:    389
-Disjuncts:    204
+Unifications: 179
+Conjuncts:    595
+Disjuncts:    24
-- out/eval/stats --
Leaks:  43
Freed:  170
Reused: 164
Allocs: 49
Retain: 44

Unifications: 199
Conjuncts:    389
Disjuncts:    204
-- out/evalalpha --
Errors:
b.x: field not allowed:
    ./in.cue:5:9

Result:
(_|_){
  // [eval]
  a: (#struct){
    a: (struct){
      b: (int){ int }
    }
  }
  b: (_|_){
    // [eval]
    x: (_|_){
      // [eval] b.x: field not allowed:
      //     ./in.cue:5:9
    }
    a: (struct){
      b: (int){ int }
    }
  }
  c: (#struct){
    a: (struct){
      c: (int){ int }
      b: (int){ int }
    }
  }
  inDisjunctions: (struct){
    x: (struct){
      socket: (#struct){
        string: (#struct){ |((#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1 = ~(inDisjunctions.x.socket.string.a)
            uint: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }, (#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1 = ~(inDisjunctions.x.socket.string.a)
            string: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }) }
      }
      syslog: (#struct){
        xxx: (#struct){ |((#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1 = ~(inDisjunctions.x.syslog.xxx.a)
            uint: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }, (#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1 = ~(inDisjunctions.x.syslog.xxx.a)
            string: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }) }
        string: (#struct){ |((#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1 = ~(inDisjunctions.x.syslog.string.a)
            uint: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }, (#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1 = ~(inDisjunctions.x.syslog.string.a)
            string: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }) }
      }
    }
    #Def: (#struct){
    }
  }
  issue642: (struct){
    test: (#struct){
      a: (struct){
        x: (_){ _ }
        y: (_){ _ }
      }
      b: (struct){
        x: (_){ _ }
        y: (_){ _ }
      }
    }
  }
  withSubfields: (struct){
    test: (#struct){
      a: (struct){
        x: (_){ _ }
        y: (_){ _ }
      }
      b: (struct){
        x: (_){ _ }
        y: (_){ _ }
      }
    }
  }
  issue3572: (struct){
    t1: (#struct){
      a: (int){ 5 }
    }
    e: (#struct){
    }
    t2: (#struct){
      a: (int){ 5 }
    }
  }
  issue3580: (struct){
    x: (#struct){
      a: (_){ _ }
      b: (_){ _ }
    }
  }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -1,7 +1,5 @@
 Errors:
 b.x: field not allowed:
-    ./in.cue:1:10
-    ./in.cue:5:4
     ./in.cue:5:9
 
 Result:
@@ -14,20 +12,18 @@
   }
   b: (_|_){
     // [eval]
-    a: (struct){
-      b: (int){ int }
-    }
     x: (_|_){
       // [eval] b.x: field not allowed:
-      //     ./in.cue:1:10
-      //     ./in.cue:5:4
       //     ./in.cue:5:9
     }
+    a: (struct){
+      b: (int){ int }
+    }
   }
   c: (#struct){
     a: (struct){
-      b: (int){ int }
       c: (int){ int }
+      b: (int){ int }
     }
   }
   inDisjunctions: (struct){
@@ -37,21 +33,17 @@
             a: (#struct){
               b: (bool){ true }
             }
-            let X#1 = (#struct){
-              b: (bool){ true }
-            }
-            uint: (#struct){
-              a: (#struct){
-                b: (bool){ true }
-              }
-            }
-          }, (#struct){
-            a: (#struct){
-              b: (bool){ true }
-            }
-            let X#1 = (#struct){
-              b: (bool){ true }
-            }
+            let X#1 = ~(inDisjunctions.x.socket.string.a)
+            uint: (#struct){
+              a: (#struct){
+                b: (bool){ true }
+              }
+            }
+          }, (#struct){
+            a: (#struct){
+              b: (bool){ true }
+            }
+            let X#1 = ~(inDisjunctions.x.socket.string.a)
             string: (#struct){
               a: (#struct){
                 b: (bool){ true }
@@ -60,42 +52,42 @@
           }) }
       }
       syslog: (#struct){
-        string: (#struct){ |((#struct){
-            a: (#struct){
-              b: (bool){ true }
-            }
-            let X#1multi = 〈0;a〉
-            uint: (#struct){
-              a: (#struct){
-                b: (bool){ true }
-              }
-            }
-          }, (#struct){
-            a: (#struct){
-              b: (bool){ true }
-            }
-            let X#1multi = 〈0;a〉
-            string: (#struct){
-              a: (#struct){
-                b: (bool){ true }
-              }
-            }
-          }) }
         xxx: (#struct){ |((#struct){
             a: (#struct){
               b: (bool){ true }
             }
-            let X#1multi = 〈0;a〉
-            uint: (#struct){
-              a: (#struct){
-                b: (bool){ true }
-              }
-            }
-          }, (#struct){
-            a: (#struct){
-              b: (bool){ true }
-            }
-            let X#1multi = 〈0;a〉
+            let X#1 = ~(inDisjunctions.x.syslog.xxx.a)
+            uint: (#struct){
+              a: (#struct){
+                b: (bool){ true }
+              }
+            }
+          }, (#struct){
+            a: (#struct){
+              b: (bool){ true }
+            }
+            let X#1 = ~(inDisjunctions.x.syslog.xxx.a)
+            string: (#struct){
+              a: (#struct){
+                b: (bool){ true }
+              }
+            }
+          }) }
+        string: (#struct){ |((#struct){
+            a: (#struct){
+              b: (bool){ true }
+            }
+            let X#1 = ~(inDisjunctions.x.syslog.string.a)
+            uint: (#struct){
+              a: (#struct){
+                b: (bool){ true }
+              }
+            }
+          }, (#struct){
+            a: (#struct){
+              b: (bool){ true }
+            }
+            let X#1 = ~(inDisjunctions.x.syslog.string.a)
             string: (#struct){
               a: (#struct){
                 b: (bool){ true }
-- diff/todo/p3 --
Reordering
Let differs.
-- out/eval --
Errors:
b.x: field not allowed:
    ./in.cue:1:10
    ./in.cue:5:4
    ./in.cue:5:9

Result:
(_|_){
  // [eval]
  a: (#struct){
    a: (struct){
      b: (int){ int }
    }
  }
  b: (_|_){
    // [eval]
    a: (struct){
      b: (int){ int }
    }
    x: (_|_){
      // [eval] b.x: field not allowed:
      //     ./in.cue:1:10
      //     ./in.cue:5:4
      //     ./in.cue:5:9
    }
  }
  c: (#struct){
    a: (struct){
      b: (int){ int }
      c: (int){ int }
    }
  }
  inDisjunctions: (struct){
    x: (struct){
      socket: (#struct){
        string: (#struct){ |((#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1 = (#struct){
              b: (bool){ true }
            }
            uint: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }, (#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1 = (#struct){
              b: (bool){ true }
            }
            string: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }) }
      }
      syslog: (#struct){
        string: (#struct){ |((#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1multi = 〈0;a〉
            uint: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }, (#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1multi = 〈0;a〉
            string: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }) }
        xxx: (#struct){ |((#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1multi = 〈0;a〉
            uint: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }, (#struct){
            a: (#struct){
              b: (bool){ true }
            }
            let X#1multi = 〈0;a〉
            string: (#struct){
              a: (#struct){
                b: (bool){ true }
              }
            }
          }) }
      }
    }
    #Def: (#struct){
    }
  }
  issue642: (struct){
    test: (#struct){
      a: (struct){
        x: (_){ _ }
        y: (_){ _ }
      }
      b: (struct){
        x: (_){ _ }
        y: (_){ _ }
      }
    }
  }
  withSubfields: (struct){
    test: (#struct){
      a: (struct){
        x: (_){ _ }
        y: (_){ _ }
      }
      b: (struct){
        x: (_){ _ }
        y: (_){ _ }
      }
    }
  }
  issue3572: (struct){
    t1: (#struct){
      a: (int){ 5 }
    }
    e: (#struct){
    }
    t2: (#struct){
      a: (int){ 5 }
    }
  }
  issue3580: (struct){
    x: (#struct){
      a: (_){ _ }
      b: (_){ _ }
    }
  }
}
-- out/compile --
--- in.cue
{
  a: close({
    a: {
      b: int
    }
  })
  b: (〈0;a〉 & {
    x: int
  })
  c: (〈0;a〉 & {
    a: {
      c: int
    }
  })
  inDisjunctions: {
    x: {
      [string]: 〈1;#Def〉
    }
    #Def: {
      [string]: {
        a: {
          b: true
        }
        let X#1 = 〈0;a〉
        (close({
          uint: {
            a: {
              b: 〈3;let X#1〉.b
            }
          }
        })|close({
          string: {
            a: {
              b: true
            }
          }
        }))
      }
    }
    x: {
      socket: {
        string: {}
      }
    }
    x: {
      syslog: 〈1;x〉.socket
    }
    x: {
      syslog: {
        xxx: {}
      }
    }
  }
  issue642: {
    test: close(({
      a: _
      b: {
        x: _
      }
    } & {
      [string]: {
        y: _
      }
    }))
    test: {
      a: {
        x: _
      }
    }
    test: {
      b: {
        x: _
      }
    }
  }
  withSubfields: {
    test: close({
      a: _
      b: {
        x: _
      }
      [string]: {
        y: _
      }
    })
    test: {
      a: {
        x: _
      }
    }
    test: {
      b: {
        x: _
      }
    }
  }
  issue3572: {
    t1: (close({
      ...
    }) & {
      a: 5
    })
    e: close({
      ...
    })
    t2: (〈0;e〉 & {
      a: 5
    })
  }
  issue3580: {
    x: close({
      a: _
      b: 〈1;x〉.a
    })
  }
}
