testdata: convert old tests to txtar format

Also populates different output formats based on the current
compiler and exporter.

This data is to be used as test input for the new evaluator,
but can also be used as a base for other implemenations.

Initially, these tests are generated with gen.go and are mapped
corrponding to the original test. This allows parallel development
while keeping the tests in sync.

Eventually, these tests will stand on their own. At that point they
can be reorganized reflecting functionality rather the internals
of the told implementation.

Change-Id: Ie99acc678e2a13647eb1cd12fbee3337c05e34b5
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5821
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/export_test.go b/cue/export_test.go
index 3743a4a..b531b23 100644
--- a/cue/export_test.go
+++ b/cue/export_test.go
@@ -24,12 +24,15 @@
 )
 
 func TestExport(t *testing.T) {
-	testCases := []struct {
+	// Do not inline: the named struct is used as a marker in
+	// testdata/gen.go.
+	type exportTest struct {
 		raw     bool // skip evaluation the root, fully raw
 		eval    bool // evaluate the full export
 		noOpt   bool
 		in, out string
-	}{{
+	}
+	testCases := []exportTest{{
 		in:  `"hello"`,
 		out: `"hello"`,
 	}, {
diff --git a/cue/subsume_test.go b/cue/subsume_test.go
index 3d10d36..e11681b 100644
--- a/cue/subsume_test.go
+++ b/cue/subsume_test.go
@@ -22,12 +22,15 @@
 )
 
 func TestSubsume(t *testing.T) {
-	testCases := []struct {
+	// Do not inline: the named struct is used as a marker in
+	// testdata/gen.go.
+	type subsumeTest struct {
 		// the result of b ⊑ a, where a and b are defined in "in"
 		subsumes bool
 		in       string
 		mode     subsumeMode
-	}{
+	}
+	testCases := []subsumeTest{
 		// Top subsumes everything
 		0: {subsumes: true, in: `a: _, b: _ `},
 		1: {subsumes: true, in: `a: _, b: null `},
diff --git a/cue/testdata/basicrewrite/000_errors.txtar b/cue/testdata/basicrewrite/000_errors.txtar
new file mode 100644
index 0000000..ca4b21e
--- /dev/null
+++ b/cue/testdata/basicrewrite/000_errors.txtar
@@ -0,0 +1,18 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: errors
+#evalPartial
+-- in.cue --
+a: _|_ & _|_
+b: null & _|_
+c: b.a == _|_
+d: _|_ != b.a
+e: _|_ == _|_
+-- out/def --
+a: _|_ // from source
+b: _|_ // from source
+c: true
+d: false
+e: true
+-- out/legacy-debug --
+<0>{a: _|_(from source), b: _|_(from source), c: true, d: false, e: true}
diff --git a/cue/testdata/basicrewrite/001_regexp.txtar b/cue/testdata/basicrewrite/001_regexp.txtar
new file mode 100644
index 0000000..d8fad38
--- /dev/null
+++ b/cue/testdata/basicrewrite/001_regexp.txtar
@@ -0,0 +1,41 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: regexp
+#evalPartial
+-- in.cue --
+c1: "a" =~ "a"
+c2: "foo" =~ "[a-z]{3}"
+c3: "foo" =~ "[a-z]{4}"
+c4: "foo" !~ "[a-z]{4}"
+
+b1: =~"a"
+b1: "a"
+b2: =~"[a-z]{3}"
+b2: "foo"
+b3: =~"[a-z]{4}"
+b3: "foo"
+b4: !~"[a-z]{4}"
+b4: "foo"
+
+s1: !="b" & =~"c"     // =~"c"
+s2: !="b" & =~"[a-z]" // != "b" & =~"[a-z]"
+
+e1: "foo" =~ 1
+e2: "foo" !~ true
+e3: !="a" & <5
+-- out/def --
+c1: true
+c2: true
+c3: false
+c4: true
+b1: "a"
+b2: "foo"
+b3: _|_ // invalid value "foo" (does not match =~"[a-z]{4}")
+b4: "foo"
+s1: =~"c"
+s2: !="b" & =~"[a-z]"
+e1: _|_ // invalid operation "foo" =~ 1 (mismatched types string and int)
+e2: _|_ // invalid operation "foo" !~ true (mismatched types string and bool)
+e3: _|_ // conflicting values !="a" and <5 (mismatched types string and number)
+-- out/legacy-debug --
+<0>{c1: true, c2: true, c3: false, c4: true, b1: "a", b2: "foo", b3: _|_((=~"[a-z]{4}" & "foo"):invalid value "foo" (does not match =~"[a-z]{4}")), b4: "foo", s1: =~"c", s2: (!="b" & =~"[a-z]"), e1: _|_(("foo" =~ 1):invalid operation "foo" =~ 1 (mismatched types string and int)), e2: _|_(("foo" !~ true):invalid operation "foo" !~ true (mismatched types string and bool)), e3: _|_((!="a" & <5):conflicting values !="a" and <5 (mismatched types string and number))}
diff --git a/cue/testdata/basicrewrite/002_arithmetic.txtar b/cue/testdata/basicrewrite/002_arithmetic.txtar
new file mode 100644
index 0000000..e76baf1
--- /dev/null
+++ b/cue/testdata/basicrewrite/002_arithmetic.txtar
@@ -0,0 +1,68 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: arithmetic
+#evalPartial
+-- in.cue --
+i1: 1 & int
+i2: 2 & int
+
+sum:     -1 + +2     // 1
+div1:    2.0 / 3 * 6 // 4
+div2:    2 / 3 * 6   // 4
+div3:    1.00 / 1.00
+divZero: 1.0 / 0
+div00:   0 / 0
+b:       1 != 4
+add:     div1 + 1.0
+
+idiv00: 0 div 0
+imod00: 0 mod 0
+iquo00: 0 quo 0
+irem00: 0 rem 0
+
+v1: 1.0T / 2.0
+v2: 2.0 == 2
+v3: 2.0 / 3.0
+v5: i1 div i2
+
+e0: 2 + "a"
+// these are now all alloweed
+// e1: 2.0 / i1
+// e2: i1 / 2.0
+// e3: 3.0 % i2
+// e4: i1 % 2.0
+e5: 1.0 div 2
+e6: 2 rem 2.0
+e7: 2 quo 2.0
+e8: 1.0 mod 1
+-- out/def --
+i1:      1
+i2:      2
+sum:     1
+div1:    4.00000000000000000000000
+div2:    4.00000000000000000000000
+div3:    1.
+divZero: _|_ // division by zero
+div00:   _|_ // division undefined
+b:       true
+add:     5.00000000000000000000000
+idiv00:  _|_ // division by zero
+imod00:  _|_ // division by zero
+iquo00:  _|_ // division by zero
+irem00:  _|_ // division by zero
+v1:      5.0000000000e+11
+v2:      true
+v3:      0.666666666666666666666667
+v5:      0
+e0:      _|_ // invalid operation 2 + "a" (mismatched types int and string)
+// these are now all alloweed
+// e1: 2.0 / i1
+// e2: i1 / 2.0
+// e3: 3.0 % i2
+// e4: i1 % 2.0
+e5: _|_ // invalid operation 1.0 div 2 (mismatched types float and int)
+e6: _|_ // invalid operation 2 rem 2.0 (mismatched types int and float)
+e7: _|_ // invalid operation 2 quo 2.0 (mismatched types int and float)
+e8: _|_ // invalid operation 1.0 mod 1 (mismatched types float and int)
+-- out/legacy-debug --
+<0>{i1: 1, i2: 2, sum: 1, div1: 4.00000000000000000000000, div2: 4.00000000000000000000000, div3: 1., divZero: _|_((1.0 / 0):division by zero), div00: _|_((0 / 0):division undefined), b: true, add: 5.00000000000000000000000, idiv00: _|_((0 div 0):division by zero), imod00: _|_((0 mod 0):division by zero), iquo00: _|_((0 quo 0):division by zero), irem00: _|_((0 rem 0):division by zero), v1: 5.0000000000e+11, v2: true, v3: 0.666666666666666666666667, v5: 0, e0: _|_((2 + "a"):invalid operation 2 + "a" (mismatched types int and string)), e5: _|_((1.0 div 2):invalid operation 1.0 div 2 (mismatched types float and int)), e6: _|_((2 rem 2.0):invalid operation 2 rem 2.0 (mismatched types int and float)), e7: _|_((2 quo 2.0):invalid operation 2 quo 2.0 (mismatched types int and float)), e8: _|_((1.0 mod 1):invalid operation 1.0 mod 1 (mismatched types float and int))}
diff --git a/cue/testdata/basicrewrite/003_integer-specific arithmetic.txtar b/cue/testdata/basicrewrite/003_integer-specific arithmetic.txtar
new file mode 100644
index 0000000..ef3acec
--- /dev/null
+++ b/cue/testdata/basicrewrite/003_integer-specific arithmetic.txtar
@@ -0,0 +1,59 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: integer-specific arithmetic
+#evalPartial
+-- in.cue --
+q1:  5 quo 2   // 2
+q2:  5 quo -2  // -2
+q3:  -5 quo 2  // -2
+q4:  -5 quo -2 // 2
+qe1: 2.0 quo 1
+qe2: 2 quo 1.0
+
+r1:  5 rem 2   // 1
+r2:  5 rem -2  // 1
+r3:  -5 rem 2  // -1
+r4:  -5 rem -2 // -1
+re1: 2.0 rem 1
+re2: 2 rem 1.0
+
+d1:  5 div 2   // 2
+d2:  5 div -2  // -2
+d3:  -5 div 2  // -3
+d4:  -5 div -2 // 3
+de1: 2.0 div 1
+de2: 2 div 1.0
+
+m1:  5 mod 2   // 1
+m2:  5 mod -2  // 1
+m3:  -5 mod 2  // 1
+m4:  -5 mod -2 // 1
+me1: 2.0 mod 1
+me2: 2 mod 1.0
+-- out/def --
+q1:  2
+q2:  -2
+q3:  -2
+q4:  2
+qe1: _|_ // invalid operation 2.0 quo 1 (mismatched types float and int)
+qe2: _|_ // invalid operation 2 quo 1.0 (mismatched types int and float)
+r1:  1
+r2:  1
+r3:  -1
+r4:  -1
+re1: _|_ // invalid operation 2.0 rem 1 (mismatched types float and int)
+re2: _|_ // invalid operation 2 rem 1.0 (mismatched types int and float)
+d1:  2
+d2:  -2
+d3:  -3
+d4:  3
+de1: _|_ // invalid operation 2.0 div 1 (mismatched types float and int)
+de2: _|_ // invalid operation 2 div 1.0 (mismatched types int and float)
+m1:  1
+m2:  1
+m3:  1
+m4:  1
+me1: _|_ // invalid operation 2.0 mod 1 (mismatched types float and int)
+me2: _|_ // invalid operation 2 mod 1.0 (mismatched types int and float)
+-- out/legacy-debug --
+<0>{q1: 2, q2: -2, q3: -2, q4: 2, qe1: _|_((2.0 quo 1):invalid operation 2.0 quo 1 (mismatched types float and int)), qe2: _|_((2 quo 1.0):invalid operation 2 quo 1.0 (mismatched types int and float)), r1: 1, r2: 1, r3: -1, r4: -1, re1: _|_((2.0 rem 1):invalid operation 2.0 rem 1 (mismatched types float and int)), re2: _|_((2 rem 1.0):invalid operation 2 rem 1.0 (mismatched types int and float)), d1: 2, d2: -2, d3: -3, d4: 3, de1: _|_((2.0 div 1):invalid operation 2.0 div 1 (mismatched types float and int)), de2: _|_((2 div 1.0):invalid operation 2 div 1.0 (mismatched types int and float)), m1: 1, m2: 1, m3: 1, m4: 1, me1: _|_((2.0 mod 1):invalid operation 2.0 mod 1 (mismatched types float and int)), me2: _|_((2 mod 1.0):invalid operation 2 mod 1.0 (mismatched types int and float))}
diff --git a/cue/testdata/basicrewrite/004_booleans.txtar b/cue/testdata/basicrewrite/004_booleans.txtar
new file mode 100644
index 0000000..eaa5542
--- /dev/null
+++ b/cue/testdata/basicrewrite/004_booleans.txtar
@@ -0,0 +1,17 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: booleans
+#evalPartial
+-- in.cue --
+t: true
+t: !false
+f: false
+f: !t
+e: true
+e: !true
+-- out/def --
+t: true
+f: false
+e: _|_ // conflicting values true and false
+-- out/legacy-debug --
+<0>{t: true, f: false, e: _|_(true:conflicting values true and false)}
diff --git a/cue/testdata/basicrewrite/005_boolean arithmetic.txtar b/cue/testdata/basicrewrite/005_boolean arithmetic.txtar
new file mode 100644
index 0000000..1f96a59
--- /dev/null
+++ b/cue/testdata/basicrewrite/005_boolean arithmetic.txtar
@@ -0,0 +1,20 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: boolean arithmetic
+#evalPartial
+-- in.cue --
+a: true && true
+b: true || false
+c: false == true
+d: false != true
+e: true & true
+f: true & false
+-- out/def --
+a: true
+b: true
+c: false
+d: true
+e: true
+f: _|_ // conflicting values true and false
+-- out/legacy-debug --
+<0>{a: true, b: true, c: false, d: true, e: true, f: _|_(true:conflicting values true and false)}
diff --git a/cue/testdata/basicrewrite/006_basic type.txtar b/cue/testdata/basicrewrite/006_basic type.txtar
new file mode 100644
index 0000000..651f134
--- /dev/null
+++ b/cue/testdata/basicrewrite/006_basic type.txtar
@@ -0,0 +1,22 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: basic type
+#evalPartial
+-- in.cue --
+a: 1 & int
+b: number & 1
+c: 1.0
+c: float
+d: int & float // _|_
+e: "4" & string
+f: true
+f: bool
+-- out/def --
+a: 1
+b: 1
+c: 1.0
+d: _|_ // conflicting values int and float (mismatched types int and float)
+e: "4"
+f: true
+-- out/legacy-debug --
+<0>{a: 1, b: 1, c: 1.0, d: _|_((int & float):conflicting values int and float (mismatched types int and float)), e: "4", f: true}
diff --git a/cue/testdata/basicrewrite/007_strings and bytes.txtar b/cue/testdata/basicrewrite/007_strings and bytes.txtar
new file mode 100644
index 0000000..1d3b842
--- /dev/null
+++ b/cue/testdata/basicrewrite/007_strings and bytes.txtar
@@ -0,0 +1,29 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: strings and bytes
+#evalPartial
+-- in.cue --
+s0: "foo" + "bar"
+s1: 3 * "abc"
+s2: "abc" * 2
+
+b0: 'foo' + 'bar'
+b1: 3 * 'abc'
+b2: 'abc' * 2
+
+// TODO: consider the semantics of this and perhaps allow this.
+e0: "a" + ''
+e1: 'b' + "c"
+-- out/def --
+s0: "foobar"
+s1: "abcabcabc"
+s2: "abcabc"
+b0: 'foobar'
+b1: 'abcabcabc'
+b2: 'abcabc'
+
+// TODO: consider the semantics of this and perhaps allow this.
+e0: _|_ // invalid operation "a" + '' (mismatched types string and bytes)
+e1: _|_ // invalid operation 'b' + "c" (mismatched types bytes and string)
+-- out/legacy-debug --
+<0>{s0: "foobar", s1: "abcabcabc", s2: "abcabc", b0: 'foobar', b1: 'abcabcabc', b2: 'abcabc', e0: _|_(("a" + ''):invalid operation "a" + '' (mismatched types string and bytes)), e1: _|_(('b' + "c"):invalid operation 'b' + "c" (mismatched types bytes and string))}
diff --git a/cue/testdata/basicrewrite/008_escaping.txtar b/cue/testdata/basicrewrite/008_escaping.txtar
new file mode 100644
index 0000000..5a02e06
--- /dev/null
+++ b/cue/testdata/basicrewrite/008_escaping.txtar
@@ -0,0 +1,38 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: escaping
+#evalPartial
+-- in.cue --
+a: "foo\nbar"
+b: a
+
+// TODO: mimic http://exploringjs.com/es6/ch_template-literals.html#sec_introduction-template-literals
+-- out/def --
+a: """
+        foo
+        bar
+        """
+b: """
+        foo
+        bar
+        """
+-- out/export --
+a: """
+        foo
+        bar
+        """
+b: """
+        foo
+        bar
+        """
+-- out/yaml --
+a: |-
+  foo
+  bar
+b: |-
+  foo
+  bar
+-- out/json --
+{"a":"foo\nbar","b":"foo\nbar"}
+-- out/legacy-debug --
+<0>{a: "foo\nbar", b: "foo\nbar"}
diff --git a/cue/testdata/basicrewrite/009_reference.txtar b/cue/testdata/basicrewrite/009_reference.txtar
new file mode 100644
index 0000000..b113beb
--- /dev/null
+++ b/cue/testdata/basicrewrite/009_reference.txtar
@@ -0,0 +1,64 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: reference
+#evalPartial
+-- in.cue --
+a: b
+b: 2
+d: {
+	d: 3
+	e: d
+}
+e: {
+	e: {
+		v: 1
+	}
+	f: {
+		v: e.v
+	}
+}
+-- out/def --
+a: 2
+b: 2
+d: {
+	d: 3
+	e: 3
+}
+e: {
+	e: {
+		v: 1
+	}
+	f: {
+		v: 1
+	}
+}
+-- out/export --
+a: 2
+b: 2
+d: {
+	d: 3
+	e: 3
+}
+e: {
+	e: {
+		v: 1
+	}
+	f: {
+		v: 1
+	}
+}
+-- out/yaml --
+a: 2
+b: 2
+d:
+  d: 3
+  e: 3
+e:
+  e:
+    v: 1
+  f:
+    v: 1
+-- out/json --
+{"a":2,"b":2,"d":{"d":3,"e":3},"e":{"e":{"v":1},"f":{"v":1}}}
+-- out/legacy-debug --
+<0>{a: 2, b: 2, d: <1>{d: 3, e: 3}, e: <2>{e: <3>{v: 1}, f: <4>{v: 1}}}
diff --git a/cue/testdata/basicrewrite/010_lists.txtar b/cue/testdata/basicrewrite/010_lists.txtar
new file mode 100644
index 0000000..d8f6c7b
--- /dev/null
+++ b/cue/testdata/basicrewrite/010_lists.txtar
@@ -0,0 +1,26 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: lists
+#evalPartial
+-- in.cue --
+list: [1, 2, 3]
+index: [1, 2, 3][1]
+unify: [1, 2, 3] & [_, 2, 3]
+e:     [] & 4
+e2:    [3]["d"]
+e3:    [3][-1]
+e4:    [1, 2, ...>=4 & <=5] & [1, 2, 4, 8]
+e5:    [1, 2, 4, 8] & [1, 2, ...>=4 & <=5]
+-- out/def --
+list: [1, 2, 3]
+index: 2
+unify: [1, 2, 3]
+e:  _|_ // conflicting values [] and 4 (mismatched types list and int)
+e2: _|_ // invalid list index "d" (type string)
+e3: _|_ // invalid list index -1 (index must be non-negative)
+e4: [1, 2, 4, _|_, // invalid value 8 (out of bound <=5)
+]
+e5: [1, 2, 4, _|_, // invalid value 8 (out of bound <=5)
+]
+-- out/legacy-debug --
+<0>{list: [1,2,3], index: 2, unify: [1,2,3], e: _|_(([] & 4):conflicting values [] and 4 (mismatched types list and int)), e2: _|_("d":invalid list index "d" (type string)), e3: _|_(-1:invalid list index -1 (index must be non-negative)), e4: [1,2,4,_|_((<=5 & 8):invalid value 8 (out of bound <=5))], e5: [1,2,4,_|_((<=5 & 8):invalid value 8 (out of bound <=5))]}
diff --git a/cue/testdata/basicrewrite/011_list arithmetic.txtar b/cue/testdata/basicrewrite/011_list arithmetic.txtar
new file mode 100644
index 0000000..2b95dd3
--- /dev/null
+++ b/cue/testdata/basicrewrite/011_list arithmetic.txtar
@@ -0,0 +1,26 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: list arithmetic
+#evalPartial
+-- in.cue --
+list: [1, 2, 3]
+mul0: list * 0
+mul1: list * 1
+mul2: 2 * list
+list1: [1]
+mul1_0: list1 * 0
+mul1_1: 1 * list1
+mul1_2: list1 * 2
+e:      list * -1
+-- out/def --
+list: [1, 2, 3]
+mul0: []
+mul1: [1, 2, 3]
+mul2: [1, 2, 3, 1, 2, 3]
+list1: [1]
+mul1_0: []
+mul1_1: [1]
+mul1_2: [1, 1]
+e: _|_ // negative number -1 multiplies list
+-- out/legacy-debug --
+<0>{list: [1,2,3], mul0: [], mul1: [1,2,3], mul2: [1,2,3,1,2,3], list1: [1], mul1_0: [], mul1_1: [1], mul1_2: [1,1], e: _|_((<1>.list * -1):negative number -1 multiplies list)}
diff --git a/cue/testdata/basicrewrite/012_selecting.txtar b/cue/testdata/basicrewrite/012_selecting.txtar
new file mode 100644
index 0000000..216d810
--- /dev/null
+++ b/cue/testdata/basicrewrite/012_selecting.txtar
@@ -0,0 +1,29 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: selecting
+#evalPartial
+-- in.cue --
+obj: {a: 1, b: 2}
+index:  {a: 1, b:     2}["b"]
+mulidx: {a: 1, b: {a: 1, b: 3}}["b"]["b"]
+e:      {a: 1}[4]
+f:      {a: 1}.b
+g:      {a: 1}["b"]
+h:      [3].b
+-- out/def --
+obj: {
+	a: 1
+	b: 2
+}
+index:  2
+mulidx: 3
+e:      _|_ // invalid struct index 4 (type int)
+f:      {
+	a: 1
+}.b
+g: {
+	a: 1
+}["b"]
+h: _|_ // invalid operation: [3].b (type list does not support selection)
+-- out/legacy-debug --
+<0>{obj: <1>{a: 1, b: 2}, index: 2, mulidx: 3, e: _|_(4:invalid struct index 4 (type int)), f: <2>{a: 1}.b, g: <3>{a: 1}["b"], h: _|_([3]:invalid operation: [3].b (type list does not support selection))}
diff --git a/cue/testdata/basicrewrite/013_obj unify.txtar b/cue/testdata/basicrewrite/013_obj unify.txtar
new file mode 100644
index 0000000..dceb8c2
--- /dev/null
+++ b/cue/testdata/basicrewrite/013_obj unify.txtar
@@ -0,0 +1,33 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: obj unify
+#evalPartial
+-- in.cue --
+o1: {a: 1} & {b: 2}       // {a:1,b:2}
+o2: {a: 1, b:    2} & {b: 2} // {a:1,b:2}
+o3: {a: 1} & {a: 1, b:    2} // {a:1,b:2}
+o4: {a: 1} & {b: 2}       // {a:1,b:2}
+o4: {a: 1, b:    2} & {b: 2}
+o4: {a: 1} & {a: 1, b:    2}
+e:  1   // 1 & {a:3}
+e: {a: 3}
+-- out/def --
+o1: {
+	a: 1
+	b: 2
+}
+o2: {
+	a: 1
+	b: 2
+}
+o3: {
+	a: 1
+	b: 2
+}
+o4: {
+	a: 1
+	b: 2
+}
+e: _|_ // conflicting values 1 and {a: 3} (mismatched types int and struct)
+-- out/legacy-debug --
+<0>{o1: <1>{a: 1, b: 2}, o2: <2>{a: 1, b: 2}, o3: <3>{a: 1, b: 2}, o4: <4>{a: 1, b: 2}, e: _|_((1 & <5>{a: 3}):conflicting values 1 and {a: 3} (mismatched types int and struct))}
diff --git a/cue/testdata/basicrewrite/014_disjunctions.txtar b/cue/testdata/basicrewrite/014_disjunctions.txtar
new file mode 100644
index 0000000..7d5a40c
--- /dev/null
+++ b/cue/testdata/basicrewrite/014_disjunctions.txtar
@@ -0,0 +1,58 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: disjunctions
+#evalPartial
+-- in.cue --
+o1:  1 | 2 | 3
+o2:  (1 | 2 | 3) & 1
+o3:  2 & (1 | *2 | 3)
+o4:  (1 | *2 | 3) & (1 | 2 | *3)
+o5:  (1 | *2 | 3) & (3 | *2 | 1)
+o6:  (1 | 2 | 3) & (3 | 1 | 2)
+o7:  (1 | 2 | 3) & (2 | 3)
+o8:  (1 | 2 | 3) & (3 | 2)
+o9:  (2 | 3) & (1 | 2 | 3)
+o10: (3 | 2) & (1 | *2 | 3)
+
+m1: (*1 | (*2 | 3)) & (>=2 & <=3)
+m2: (*1 | (*2 | 3)) & (2 | 3)
+m3: (*1 | *(*2 | 3)) & (2 | 3)
+m4: (2 | 3) & (*2 | 3)
+m5: (*2 | 3) & (2 | 3)
+
+// (*2 | 3) & (2 | 3)
+// (2 | 3) & (*2 | 3)
+// 2&(*2 | 3) | 3&(*2 | 3)
+// (*1 | (*2 | 3)) & (2 | 3)
+// *1& (2 | 3) | (*2 | 3)&(2 | 3)
+// *2&(2 | 3) | 3&(2 | 3)
+
+// (2 | 3)&(*1 | (*2 | 3))
+// 2&(*1 | (*2 | 3)) | 3&(*1 | (*2 | 3))
+// *1&2 | (*2 | 3)&2 | *1&3 | (*2 | 3)&3
+// (*2 | 3)&2 | (*2 | 3)&3
+// *2 | 3
+
+// All errors are treated the same as per the unification model.
+i1: [1, 2][3] | "c"
+-- out/def --
+o1:  1 | 2 | 3
+o2:  1
+o3:  2
+o4:  1 | 2 | 3 | *_|_
+o5:  1 | *2 | 3
+o6:  1 | 2 | 3
+o7:  2 | 3
+o8:  2 | 3
+o9:  2 | 3
+o10: 3 | *2
+m1:  *2 | 3
+m2:  *2 | 3
+m3:  *2 | 3
+m4:  *2 | 3
+m5:  *2 | 3
+
+// All errors are treated the same as per the unification model.
+i1: "c"
+-- out/legacy-debug --
+<0>{o1: (1 | 2 | 3), o2: 1, o3: 2, o4: (1 | 2 | 3 | *_|_), o5: (1 | *2 | 3), o6: (1 | 2 | 3), o7: (2 | 3), o8: (2 | 3), o9: (2 | 3), o10: (3 | *2), m1: (*2 | 3), m2: (*2 | 3), m3: (*2 | 3), m4: (*2 | 3), m5: (*2 | 3), i1: "c"}
diff --git a/cue/testdata/basicrewrite/015_types.txtar b/cue/testdata/basicrewrite/015_types.txtar
new file mode 100644
index 0000000..684bcc6
--- /dev/null
+++ b/cue/testdata/basicrewrite/015_types.txtar
@@ -0,0 +1,26 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: types
+#evalPartial
+-- in.cue --
+i:  int
+j:  int & 3
+s:  string
+t:  "s" & string
+e:  int & string
+e2: 1 & string
+b:  !int
+p:  +true
+m:  -false
+-- out/def --
+i:  int
+j:  3
+s:  string
+t:  "s"
+e:  _|_ // conflicting values int and string (mismatched types int and string)
+e2: _|_ // conflicting values 1 and string (mismatched types int and string)
+b:  _|_ // invalid operation !int (! int)
+p:  _|_ // invalid operation +true (+ bool)
+m:  _|_ // invalid operation -false (- bool)
+-- out/legacy-debug --
+<0>{i: int, j: 3, s: string, t: "s", e: _|_((int & string):conflicting values int and string (mismatched types int and string)), e2: _|_((1 & string):conflicting values 1 and string (mismatched types int and string)), b: _|_(!int:invalid operation !int (! int)), p: _|_(+true:invalid operation +true (+ bool)), m: _|_(-false:invalid operation -false (- bool))}
diff --git a/cue/testdata/basicrewrite/016_comparison.txtar b/cue/testdata/basicrewrite/016_comparison.txtar
new file mode 100644
index 0000000..9c85001
--- /dev/null
+++ b/cue/testdata/basicrewrite/016_comparison.txtar
@@ -0,0 +1,25 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: comparison
+#evalPartial
+-- in.cue --
+lss: 1 < 2
+leq: 1 <= 1.0
+leq: 2.0 <= 3
+eql: 1 == 1.0
+neq: 1.0 == 1
+gtr: !(2 > 3)
+geq: 2.0 >= 2
+seq: "a"+"b" == "ab"
+err: 2 == "s"
+-- out/def --
+lss: true
+leq: true
+eql: true
+neq: true
+gtr: true
+geq: true
+seq: true
+err: _|_ // invalid operation 2 == "s" (mismatched types int and string)
+-- out/legacy-debug --
+<0>{lss: true, leq: true, eql: true, neq: true, gtr: true, geq: true, seq: true, err: _|_((2 == "s"):invalid operation 2 == "s" (mismatched types int and string))}
diff --git a/cue/testdata/basicrewrite/017_null.txtar b/cue/testdata/basicrewrite/017_null.txtar
new file mode 100644
index 0000000..38ddb51
--- /dev/null
+++ b/cue/testdata/basicrewrite/017_null.txtar
@@ -0,0 +1,26 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: null
+#evalPartial
+-- in.cue --
+eql: null == null
+neq: null != null
+unf: null & null
+
+// errors
+eq1:  null == 1
+eq2:  1 == null
+ne1:  "s" != null
+call: null()
+-- out/def --
+eql: true
+neq: false
+unf: null
+
+// errors
+eq1:  false
+eq2:  false
+ne1:  true
+call: _|_ // cannot call non-function null (type null)
+-- out/legacy-debug --
+<0>{eql: true, neq: false, unf: null, eq1: false, eq2: false, ne1: true, call: _|_(null:cannot call non-function null (type null))}
diff --git a/cue/testdata/basicrewrite/018_self-reference cycles.txtar b/cue/testdata/basicrewrite/018_self-reference cycles.txtar
new file mode 100644
index 0000000..fc428bf
--- /dev/null
+++ b/cue/testdata/basicrewrite/018_self-reference cycles.txtar
@@ -0,0 +1,15 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: self-reference cycles
+#evalPartial
+-- in.cue --
+a: b - 100
+b: a + 100
+
+c: [c[1], c[0]]
+-- out/def --
+a: b - 100
+b: a + 100
+c: [c[1], c[0]]
+-- out/legacy-debug --
+<0>{a: (<1>.b - 100), b: (<1>.a + 100), c: [<1>.c[1],<1>.c[0]]}
diff --git a/cue/testdata/basicrewrite/019_resolved self-reference cycles.txtar b/cue/testdata/basicrewrite/019_resolved self-reference cycles.txtar
new file mode 100644
index 0000000..337da3d
--- /dev/null
+++ b/cue/testdata/basicrewrite/019_resolved self-reference cycles.txtar
@@ -0,0 +1,68 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: resolved self-reference cycles
+#evalPartial
+-- in.cue --
+a: b - 100
+b: a + 100
+b: 200
+
+c: [c[1], a]
+
+s1: s2 & {a: 1}
+s2: s3 & {b: 2}
+s3: s1 & {c: 3}
+-- out/def --
+a: 100
+b: 200
+c: [100, 100]
+s1: s2 & {
+	a: 1
+}
+s2: s3 & {
+	b: 2
+}
+s3: s1 & {
+	c: 3
+}
+-- out/export --
+a: 100
+b: 200
+c: [100, 100]
+s1: {
+	a: 1
+	b: 2
+	c: 3
+}
+s2: {
+	a: 1
+	b: 2
+	c: 3
+}
+s3: {
+	a: 1
+	b: 2
+	c: 3
+}
+-- out/yaml --
+a: 100
+b: 200
+c:
+- 100
+- 100
+s1:
+  a: 1
+  b: 2
+  c: 3
+s2:
+  a: 1
+  b: 2
+  c: 3
+s3:
+  a: 1
+  b: 2
+  c: 3
+-- out/json --
+{"a":100,"b":200,"c":[100,100],"s1":{"a":1,"b":2,"c":3},"s2":{"a":1,"b":2,"c":3},"s3":{"a":1,"b":2,"c":3}}
+-- out/legacy-debug --
+<0>{a: 100, b: 200, c: [100,100], s1: <1>{a: 1, b: 2, c: 3}, s2: <2>{a: 1, b: 2, c: 3}, s3: <3>{a: 1, b: 2, c: 3}}
diff --git a/cue/testdata/basicrewrite/020_resolved self-reference cycles: Issue 19.txtar b/cue/testdata/basicrewrite/020_resolved self-reference cycles: Issue 19.txtar
new file mode 100644
index 0000000..701db61
--- /dev/null
+++ b/cue/testdata/basicrewrite/020_resolved self-reference cycles: Issue 19.txtar
@@ -0,0 +1,40 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: resolved self-reference cycles: Issue 19
+#evalPartial
+-- in.cue --
+	// CUE knows how to resolve the following:
+x: y + 100
+y: x - 100
+x: 200
+
+z1: z2 + 1
+z2: z3 + 2
+z3: z1 - 3
+z3: 8
+
+// TODO: extensive tests with disjunctions.
+-- out/def --
+	// CUE knows how to resolve the following:
+x:  200
+y:  100
+z1: 11
+z2: 10
+z3: 8
+-- out/export --
+	// CUE knows how to resolve the following:
+x:  200
+y:  100
+z1: 11
+z2: 10
+z3: 8
+-- out/yaml --
+x: 200
+y: 100
+z1: 11
+z2: 10
+z3: 8
+-- out/json --
+{"x":200,"y":100,"z1":11,"z2":10,"z3":8}
+-- out/legacy-debug --
+<0>{x: 200, y: 100, z1: 11, z2: 10, z3: 8}
diff --git a/cue/testdata/basicrewrite/021_delayed constraint failure.txtar b/cue/testdata/basicrewrite/021_delayed constraint failure.txtar
new file mode 100644
index 0000000..7bc334e
--- /dev/null
+++ b/cue/testdata/basicrewrite/021_delayed constraint failure.txtar
@@ -0,0 +1,17 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: delayed constraint failure
+#evalPartial
+-- in.cue --
+a: b - 100
+b: a + 110
+b: 200
+
+x: 100
+x: x + 1
+-- out/def --
+x: _|_ // conflicting values 100 and 101
+a: _|_ // conflicting values 210 and 200
+b: _|_ // conflicting values 210 and 200
+-- out/legacy-debug --
+<0>{x: _|_((100 & 101):conflicting values 100 and 101), a: _|_((210 & 200):conflicting values 210 and 200), b: _|_((210 & 200):conflicting values 210 and 200)}
diff --git a/cue/testdata/choosedefault/000_pick first.txtar b/cue/testdata/choosedefault/000_pick first.txtar
new file mode 100644
index 0000000..61c0009
--- /dev/null
+++ b/cue/testdata/choosedefault/000_pick first.txtar
@@ -0,0 +1,35 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: pick first
+#bug: true
+#evalFull
+-- in.cue --
+a: *5 | "a" | true
+b: c: *{
+	a: 2
+} | {
+	a: 3
+}
+-- out/def --
+a: *5 | "a" | true
+b: {
+	c: *{
+		a: 2
+	} | {
+		a: 3
+	}
+}
+-- out/export --
+a: 5
+b: {
+	c: *{
+		a: 2
+	} | {
+		a: 3
+	}
+}
+-- out/yaml --
+-- out/json --
+{"a":5,"b":{"c":{"a":2}}}
+-- out/legacy-debug --
+<0>{a: 5, b: <1>{c: <2>{a: 2}}}
diff --git a/cue/testdata/choosedefault/001_simple disambiguation conflict.txtar b/cue/testdata/choosedefault/001_simple disambiguation conflict.txtar
new file mode 100644
index 0000000..5cc03ac
--- /dev/null
+++ b/cue/testdata/choosedefault/001_simple disambiguation conflict.txtar
@@ -0,0 +1,14 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: simple disambiguation conflict
+#evalFull
+-- in.cue --
+a: *"a" | "b"
+b: *"b" | "a"
+c: a & b
+-- out/def --
+a: *"a" | "b"
+b: *"b" | "a"
+c: a & b
+-- out/legacy-debug --
+<0>{a: "a", b: "b", c: ("a" | "b")}
diff --git a/cue/testdata/choosedefault/002_associativity of defaults.txtar b/cue/testdata/choosedefault/002_associativity of defaults.txtar
new file mode 100644
index 0000000..e06d112
--- /dev/null
+++ b/cue/testdata/choosedefault/002_associativity of defaults.txtar
@@ -0,0 +1,18 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: associativity of defaults
+#evalFull
+-- in.cue --
+a: *"a" | ("b" | "c")
+b: (*"a" | "b") | "c"
+c: *"a" | (*"b" | "c")
+x: a & b
+y: b & c
+-- out/def --
+x: a & b
+y: b & c
+a: *"a" | "b" | "c"
+b: *"a" | "b" | "c"
+c: *"a" | *"b" | "c"
+-- out/legacy-debug --
+<0>{x: "a", y: (*"a" | *"b"), a: "a", b: "a", c: (*"a" | *"b")}
diff --git a/cue/testdata/export/000.txtar b/cue/testdata/export/000.txtar
new file mode 100644
index 0000000..5292869
--- /dev/null
+++ b/cue/testdata/export/000.txtar
@@ -0,0 +1,14 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+"hello"
+-- out/def --
+"hello"
+-- out/export --
+"hello"
+-- out/yaml --
+hello
+-- out/json --
+"hello"
+-- out/legacy-debug --
+"hello"
diff --git a/cue/testdata/export/001.txtar b/cue/testdata/export/001.txtar
new file mode 100644
index 0000000..ade9f7e
--- /dev/null
+++ b/cue/testdata/export/001.txtar
@@ -0,0 +1,14 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+'hello'
+-- out/def --
+'hello'
+-- out/export --
+'hello'
+-- out/yaml --
+hello
+-- out/json --
+"aGVsbG8="
+-- out/legacy-debug --
+'hello'
diff --git a/cue/testdata/export/002.txtar b/cue/testdata/export/002.txtar
new file mode 100644
index 0000000..2a5247b
--- /dev/null
+++ b/cue/testdata/export/002.txtar
@@ -0,0 +1,25 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+'hello\nworld'
+-- out/def --
+'''
+        hello
+        world
+        '''
+-- out/export --
+'''
+        hello
+        world
+        '''
+-- out/yaml --
+|-
+  hello
+  world
+-- out/json --
+"aGVsbG8Kd29ybGQ="
+-- out/legacy-debug --
+'''
+        hello
+        world
+        '''
diff --git a/cue/testdata/export/003.txtar b/cue/testdata/export/003.txtar
new file mode 100644
index 0000000..a4f9850
--- /dev/null
+++ b/cue/testdata/export/003.txtar
@@ -0,0 +1,25 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+"hello\nworld"
+-- out/def --
+"""
+        hello
+        world
+        """
+-- out/export --
+"""
+        hello
+        world
+        """
+-- out/yaml --
+|-
+  hello
+  world
+-- out/json --
+"hello\nworld"
+-- out/legacy-debug --
+"""
+        hello
+        world
+        """
diff --git a/cue/testdata/export/004.txtar b/cue/testdata/export/004.txtar
new file mode 100644
index 0000000..4cd59a3
--- /dev/null
+++ b/cue/testdata/export/004.txtar
@@ -0,0 +1,14 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+{
+	$type:  3
+	"_":    int
+	"_foo": int
+	_bar:   int
+}
+-- out/def --
+$type:  3
+"_":    int
+"_foo": int
+_bar:   int
diff --git a/cue/testdata/export/005.txtar b/cue/testdata/export/005.txtar
new file mode 100644
index 0000000..3055a61
--- /dev/null
+++ b/cue/testdata/export/005.txtar
@@ -0,0 +1,11 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+{a: 1, b: a + 2, c: null, d: true, e: _, f: string}
+-- out/def --
+a: 1
+b: 3
+c: null
+d: true
+e: _
+f: string
diff --git a/cue/testdata/export/006.txtar b/cue/testdata/export/006.txtar
new file mode 100644
index 0000000..44f70a7
--- /dev/null
+++ b/cue/testdata/export/006.txtar
@@ -0,0 +1,13 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+{a: {b: 2.0, s: "abc"}, b: a.b, c: a.c, d: a["d"], e: a.t[2:3]}
+-- out/def --
+a: {
+	b: 2.0
+	s: "abc"
+}
+b: 2.0
+c: a.c
+d: a["d"]
+e: a.t[2:3]
diff --git a/cue/testdata/export/007.txtar b/cue/testdata/export/007.txtar
new file mode 100644
index 0000000..5f2eb07
--- /dev/null
+++ b/cue/testdata/export/007.txtar
@@ -0,0 +1,13 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+{a :: {b: 2.0, s: "abc"}, b: a.b, c: a.c, d: a["d"], e: a.t[2:3]}
+-- out/def --
+a :: {
+	b: 2.0
+	s: "abc"
+}
+b: 2.0
+c: _|_ // undefined field "c"
+d: _|_ // undefined field "d"
+e: _|_ // undefined field "t"
diff --git a/cue/testdata/export/008.txtar b/cue/testdata/export/008.txtar
new file mode 100644
index 0000000..2d006f4
--- /dev/null
+++ b/cue/testdata/export/008.txtar
@@ -0,0 +1,7 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+{a: [ 3 & 4]}
+-- out/def --
+a: [_|_, // conflicting values 3 and 4
+]
diff --git a/cue/testdata/export/009.txtar b/cue/testdata/export/009.txtar
new file mode 100644
index 0000000..8c66bed
--- /dev/null
+++ b/cue/testdata/export/009.txtar
@@ -0,0 +1,23 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+{
+	a: 5 * [int]
+	a: [1, 2, ...]
+	b: <=5 * [int]
+	b: [1, 2, ...]
+	c: (>=3 & <=5) * [int]
+	c: [1, 2, ...]
+	d: >=2 * [int]
+	d: [1, 2, ...]
+	e: [...int]
+	e: [1, 2, ...]
+	f: [1, 2, ...]
+}
+-- out/def --
+a: [1, 2, int, int, int]
+b: <=5*[int] & [1, 2, ...]
+c: (>=3 & <=5)*[int] & [1, 2, ...]
+d: >=2*[int] & [1, 2, ...]
+e: [1, 2, ...int]
+f: [1, 2, ...]
diff --git a/cue/testdata/export/010.txtar b/cue/testdata/export/010.txtar
new file mode 100644
index 0000000..0361a8d
--- /dev/null
+++ b/cue/testdata/export/010.txtar
@@ -0,0 +1,24 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{
+	a: 5 * [int]
+	a: [1, 2, ...]
+	b: <=5 * [int]
+	b: [1, 2, ...]
+	c: (>=3 & <=5) * [int]
+	c: [1, 2, ...]
+	d: >=2 * [int]
+	d: [1, 2, ...]
+	e: [...int]
+	e: [1, 2, ...]
+	f: [1, 2, ...]
+}
+-- out/def --
+a: [1, 2, int, int, int]
+b: <=5*[int] & [1, 2, ...]
+c: (>=3 & <=5)*[int] & [1, 2, ...]
+d: >=2*[int] & [1, 2, ...]
+e: [1, 2, ...int]
+f: [1, 2, ...]
diff --git a/cue/testdata/export/011.txtar b/cue/testdata/export/011.txtar
new file mode 100644
index 0000000..009a096
--- /dev/null
+++ b/cue/testdata/export/011.txtar
@@ -0,0 +1,24 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{a: {b: []}, c: a.b, d: a["b"]}
+-- out/def --
+a: {
+	b: []
+}
+c: []
+d: []
+-- out/export --
+a: {
+	b: []
+}
+c: []
+d: []
+-- out/yaml --
+a:
+  b: []
+c: []
+d: []
+-- out/json --
+{"a":{"b":[]},"c":[],"d":[]}
diff --git a/cue/testdata/export/012.txtar b/cue/testdata/export/012.txtar
new file mode 100644
index 0000000..97414bc
--- /dev/null
+++ b/cue/testdata/export/012.txtar
@@ -0,0 +1,8 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{a: *"foo" | *"bar" | *string | int, b: a[2:3]}
+-- out/def --
+a: *string | int
+b: _|_ // cannot slice a (type string)
diff --git a/cue/testdata/export/013.txtar b/cue/testdata/export/013.txtar
new file mode 100644
index 0000000..8de4f89
--- /dev/null
+++ b/cue/testdata/export/013.txtar
@@ -0,0 +1,8 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+{
+	a: >=0 & <=10 & !=1
+}
+-- out/def --
+a: >=0 & <=10 & !=1
diff --git a/cue/testdata/export/014.txtar b/cue/testdata/export/014.txtar
new file mode 100644
index 0000000..b4d2f57
--- /dev/null
+++ b/cue/testdata/export/014.txtar
@@ -0,0 +1,9 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{
+	a: >=0 & <=10 & !=1
+}
+-- out/def --
+a: >=0 & <=10 & !=1
diff --git a/cue/testdata/export/015.txtar b/cue/testdata/export/015.txtar
new file mode 100644
index 0000000..c817ac3
--- /dev/null
+++ b/cue/testdata/export/015.txtar
@@ -0,0 +1,12 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+-- in.cue --
+{
+	a: (*1 | 2) & (1 | *2)
+	b: [(*1 | 2) & (1 | *2)]
+}
+-- out/def --
+a: 1 | 2 | *_|_
+b: [1 | 2 | *_|_]
diff --git a/cue/testdata/export/016.txtar b/cue/testdata/export/016.txtar
new file mode 100644
index 0000000..41898ce
--- /dev/null
+++ b/cue/testdata/export/016.txtar
@@ -0,0 +1,34 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+-- in.cue --
+{
+	u16:  int & >=0 & <=65535
+	u32:  uint32
+	u64:  uint64
+	u128: uint128
+	u8:   uint8
+	ua:   uint16 & >0
+	us:   >=0 & <10_000 & int
+	i16:  >=-32768 & int & <=32767
+	i32:  int32 & >0
+	i64:  int64
+	i128: int128
+	f64:  float64
+	fi:   float64 & int
+}
+-- out/def --
+u16:  uint16
+u32:  uint32
+u64:  uint64
+u128: uint128
+u8:   uint8
+ua:   uint16 & >0
+us:   uint & <10000
+i16:  int16
+i32:  int32 & >0
+i64:  int64
+i128: int128
+f64:  float64
+fi:   int & float64
diff --git a/cue/testdata/export/017.txtar b/cue/testdata/export/017.txtar
new file mode 100644
index 0000000..4c2906b
--- /dev/null
+++ b/cue/testdata/export/017.txtar
@@ -0,0 +1,23 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{a: [1, 2], b: {for k, v in a if v > 1 {"\(k)": v}}}
+-- out/def --
+a: [1, 2]
+b: {
+	"1": 2
+}
+-- out/export --
+a: [1, 2]
+b: {
+	"1": 2
+}
+-- out/yaml --
+a:
+- 1
+- 2
+b:
+  "1": 2
+-- out/json --
+{"a":[1,2],"b":{"1":2}}
diff --git a/cue/testdata/export/018.txtar b/cue/testdata/export/018.txtar
new file mode 100644
index 0000000..fe69537
--- /dev/null
+++ b/cue/testdata/export/018.txtar
@@ -0,0 +1,20 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{a: [1, 2], b: [ for k, v in a {v}]}
+-- out/def --
+a: [1, 2]
+b: [1, 2]
+-- out/export --
+a: [1, 2]
+b: [1, 2]
+-- out/yaml --
+a:
+- 1
+- 2
+b:
+- 1
+- 2
+-- out/json --
+{"a":[1,2],"b":[1,2]}
diff --git a/cue/testdata/export/019.txtar b/cue/testdata/export/019.txtar
new file mode 100644
index 0000000..1f4e6db
--- /dev/null
+++ b/cue/testdata/export/019.txtar
@@ -0,0 +1,8 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{a: >=0 & <=10, b: "Count: \(a) times"}
+-- out/def --
+a: >=0 & <=10
+b: "Count: \(a) times"
diff --git a/cue/testdata/export/020.txtar b/cue/testdata/export/020.txtar
new file mode 100644
index 0000000..660432c
--- /dev/null
+++ b/cue/testdata/export/020.txtar
@@ -0,0 +1,16 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{a: "", b: len(a)}
+-- out/def --
+a: ""
+b: 0
+-- out/export --
+a: ""
+b: 0
+-- out/yaml --
+a: ""
+b: 0
+-- out/json --
+{"a":"","b":0}
diff --git a/cue/testdata/export/021.txtar b/cue/testdata/export/021.txtar
new file mode 100644
index 0000000..cb30238
--- /dev/null
+++ b/cue/testdata/export/021.txtar
@@ -0,0 +1,26 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+-- in.cue --
+{
+	b: {
+		idx: a[str]
+		str: string
+	}
+	b: a: b: 4
+	a: b: 3
+}
+-- out/def --
+
+A = a
+b: {
+	idx: A[str]
+	a: {
+		b: 4
+	}
+	str: string
+}
+a: {
+	b: 3
+}
diff --git a/cue/testdata/export/022.txtar b/cue/testdata/export/022.txtar
new file mode 100644
index 0000000..4c45811
--- /dev/null
+++ b/cue/testdata/export/022.txtar
@@ -0,0 +1,61 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+noOpt: true
+-- in.cue --
+{
+	job: [Name=_]: {
+		name:     Name
+		replicas: uint | *1 @protobuf(10)
+		command:  string
+	}
+
+	job: list: command: "ls"
+
+	job: nginx: {
+		command:  "nginx"
+		replicas: 2
+	}
+}
+-- out/def --
+job: {
+	{[Name=string]: {
+		name: Name, replicas: >=0 | *1 @protobuf(10), command: string
+	}}
+	list: {
+		name:     "list"
+		replicas: >=0 | *1 @protobuf(10)
+		command:  "ls"
+	}
+	nginx: {
+		name:     "nginx"
+		replicas: 2 @protobuf(10)
+		command:  "nginx"
+	}
+}
+-- out/export --
+job: {
+	list: {
+		name:     "list"
+		replicas: 1 @protobuf(10)
+		command:  "ls"
+	}
+	nginx: {
+		name:     "nginx"
+		replicas: 2 @protobuf(10)
+		command:  "nginx"
+	}
+}
+-- out/yaml --
+job:
+  list:
+    name: list
+    replicas: 1
+    command: ls
+  nginx:
+    name: nginx
+    replicas: 2
+    command: nginx
+-- out/json --
+{"job":{"list":{"name":"list","replicas":1,"command":"ls"},"nginx":{"name":"nginx","replicas":2,"command":"nginx"}}}
diff --git a/cue/testdata/export/023.txtar b/cue/testdata/export/023.txtar
new file mode 100644
index 0000000..665e738
--- /dev/null
+++ b/cue/testdata/export/023.txtar
@@ -0,0 +1,52 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{
+	emb :: {
+		a: 1
+
+		sub: {
+			f: 3
+		}
+	}
+	def :: {
+		emb
+
+		b: 2
+	}
+	f :: {a: 10}
+	e :: {
+		f
+
+		b:   int
+		[_]: <100
+		{[_]: <300}
+	}
+}
+-- out/def --
+emb :: {
+	a: 1
+	sub: {
+		f: 3
+	}
+}
+f :: {
+	a: 10
+}
+def :: {
+	b: 2
+	emb
+}
+e :: {
+	{[string]: <100}
+	b: <100
+	f
+	{[string]: <300}
+}
+-- out/export --
+
+-- out/yaml --
+{}
+-- out/json --
+{}
diff --git a/cue/testdata/export/024.txtar b/cue/testdata/export/024.txtar
new file mode 100644
index 0000000..3342808
--- /dev/null
+++ b/cue/testdata/export/024.txtar
@@ -0,0 +1,37 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+noOpt: true
+-- in.cue --
+{
+	reg: {foo: 1, bar: {baz: 3}}
+	def :: {
+		a: 1
+
+		sub: reg
+	}
+	val: def
+	def2 :: {
+		a: {b: int}
+	}
+	val2: def2
+}
+-- out/def --
+reg: {
+	foo: 1
+	bar: {
+		baz: 3
+	}
+}
+def :: {
+	a:   1
+	sub: reg
+}
+val: def
+def2 :: {
+	a: {
+		b: int
+	}
+}
+val2: def2
diff --git a/cue/testdata/export/025.txtar b/cue/testdata/export/025.txtar
new file mode 100644
index 0000000..d0c153d
--- /dev/null
+++ b/cue/testdata/export/025.txtar
@@ -0,0 +1,24 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+-- in.cue --
+{
+	b: [{
+		[X=_]: int
+		if a > 4 {
+			f: 4
+		}
+	}][a]
+	a: int
+	c: *1 | 2
+}
+-- out/def --
+b: [{
+	[X=string]: int
+	if a > 4 {
+		f: 4
+	}
+}][a]
+a: int
+c: *1 | 2
diff --git a/cue/testdata/export/026.txtar b/cue/testdata/export/026.txtar
new file mode 100644
index 0000000..0a32efc
--- /dev/null
+++ b/cue/testdata/export/026.txtar
@@ -0,0 +1,17 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+-- in.cue --
+{
+	if false {
+		{a: 1} | {b: 1}
+	}
+}
+-- out/def --
+
+-- out/export --
+
+-- out/yaml --
+{}
+-- out/json --
+{}
diff --git a/cue/testdata/export/027.txtar b/cue/testdata/export/027.txtar
new file mode 100644
index 0000000..e57d1a7
--- /dev/null
+++ b/cue/testdata/export/027.txtar
@@ -0,0 +1,20 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+-- in.cue --
+{
+	Foo :: {
+		Bar :: Foo | string
+	}
+}
+-- out/def --
+Foo :: {
+	Bar :: Foo | string
+}
+-- out/export --
+
+-- out/yaml --
+{}
+-- out/json --
+{}
diff --git a/cue/testdata/export/028.txtar b/cue/testdata/export/028.txtar
new file mode 100644
index 0000000..5c1dc14
--- /dev/null
+++ b/cue/testdata/export/028.txtar
@@ -0,0 +1,22 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+-- in.cue --
+{
+	FindInMap :: {
+		"Fn::FindInMap" :: [string | FindInMap]
+	}
+	a: [...string]
+}
+-- out/def --
+FindInMap :: {
+	"Fn::FindInMap" :: [string | FindInMap]
+}
+a: [...string]
+-- out/export --
+a: []
+-- out/yaml --
+a: []
+-- out/json --
+{"a":[]}
diff --git a/cue/testdata/export/029.txtar b/cue/testdata/export/029.txtar
new file mode 100644
index 0000000..cbcb241
--- /dev/null
+++ b/cue/testdata/export/029.txtar
@@ -0,0 +1,21 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+noOpt: true
+-- in.cue --
+{
+	And :: {
+		"Fn::And": [...(3 | And)]
+	}
+	Ands: And & {
+		"Fn::And": [_]
+	}
+}
+-- out/def --
+And :: {
+	"Fn::And": [...3 | And]
+}
+Ands: And & {
+	"Fn::And": [_]
+}
diff --git a/cue/testdata/export/030.txtar b/cue/testdata/export/030.txtar
new file mode 100644
index 0000000..36242ca
--- /dev/null
+++ b/cue/testdata/export/030.txtar
@@ -0,0 +1,38 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+-- in.cue --
+{
+	Foo :: {
+		sgl:  Bar
+		ref:  null | Foo
+		ext:  Bar | null
+		ref:  null | Foo
+		ref2: null | Foo.sgl
+		...
+	}
+	Foo :: {
+		Foo: 2
+		...
+	}
+	Bar :: string
+}
+-- out/def --
+
+FOO = Foo
+Foo :: {
+	Foo:  2
+	sgl:  Bar
+	ref:  (null | FOO) & (null | FOO)
+	ext:  Bar | null
+	ref2: null | FOO.sgl
+	...
+}
+Bar :: string
+-- out/export --
+
+-- out/yaml --
+{}
+-- out/json --
+{}
diff --git a/cue/testdata/export/031.txtar b/cue/testdata/export/031.txtar
new file mode 100644
index 0000000..247e1a5
--- /dev/null
+++ b/cue/testdata/export/031.txtar
@@ -0,0 +1,12 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+raw: true
+eval: true
+-- in.cue --
+{
+	A: [uint]
+	B: A & ([10] | [192])
+}
+-- out/def --
+A: [>=0]
+B: A & ([10] | [192])
diff --git a/cue/testdata/export/032.txtar b/cue/testdata/export/032.txtar
new file mode 100644
index 0000000..6eb06f8
--- /dev/null
+++ b/cue/testdata/export/032.txtar
@@ -0,0 +1,16 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+-- in.cue --
+{
+	[string]: _
+	foo:      3
+}
+-- out/def --
+foo: 3
+...
+-- out/export --
+foo: 3
+-- out/yaml --
+foo: 3
+-- out/json --
+{"foo":3}
diff --git a/cue/testdata/fulleval/000_detect conflicting value.txtar b/cue/testdata/fulleval/000_detect conflicting value.txtar
new file mode 100644
index 0000000..765c22e
--- /dev/null
+++ b/cue/testdata/fulleval/000_detect conflicting value.txtar
@@ -0,0 +1,11 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: detect conflicting value
+#evalFull
+-- in.cue --
+a: 8000.9
+a: 7080 | int
+-- out/def --
+a: _|_ // conflicting values 8000.9 and int (mismatched types float and int)
+-- out/legacy-debug --
+<0>{a: _|_((8000.9 & (int | int)):conflicting values 8000.9 and int (mismatched types float and int))}
diff --git a/cue/testdata/fulleval/001_conflicts in optional fields are okay .txtar b/cue/testdata/fulleval/001_conflicts in optional fields are okay .txtar
new file mode 100644
index 0000000..88aba96
--- /dev/null
+++ b/cue/testdata/fulleval/001_conflicts in optional fields are okay .txtar
@@ -0,0 +1,23 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: conflicts in optional fields are okay 
+#evalFull
+-- in.cue --
+d: {a: 1, b?: 3} | {a: 2}
+
+// the following conjunction should not eliminate any disjuncts
+c: d & {b?: 4}
+-- out/def --
+d: {
+	a:  1
+	b?: 3
+} | {
+	a: 2
+}
+
+// the following conjunction should not eliminate any disjuncts
+c: d & {
+	b?: 4
+}
+-- out/legacy-debug --
+<0>{d: (<1>{a: 1, b?: 3} | <2>{a: 2}), c: (<3>{a: 1, b?: (3 & 4)} | <4>{a: 2, b?: 4})}
diff --git a/cue/testdata/fulleval/002_resolve all disjunctions.txtar b/cue/testdata/fulleval/002_resolve all disjunctions.txtar
new file mode 100644
index 0000000..2d49d76
--- /dev/null
+++ b/cue/testdata/fulleval/002_resolve all disjunctions.txtar
@@ -0,0 +1,60 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: resolve all disjunctions
+#evalFull
+-- in.cue --
+service: [Name=string]: {
+	name: string | *Name
+	port: int | *7080
+}
+service: foo: _
+service: bar: {port: 8000}
+service: baz: {name: "foobar"}
+-- out/def --
+service: {
+	{[Name=string]: {
+		name: string | *Name, port: int | *7080
+	}}
+	foo: {
+		name: string | *"foo"
+		port: int | *7080
+	}
+	bar: {
+		name: string | *"bar"
+		port: 8000
+	}
+	baz: {
+		name: "foobar"
+		port: int | *7080
+	}
+}
+-- out/export --
+service: {
+	foo: {
+		name: "foo"
+		port: 7080
+	}
+	bar: {
+		name: "bar"
+		port: 8000
+	}
+	baz: {
+		name: "foobar"
+		port: 7080
+	}
+}
+-- out/yaml --
+service:
+  foo:
+    name: foo
+    port: 7080
+  bar:
+    name: bar
+    port: 8000
+  baz:
+    name: foobar
+    port: 7080
+-- out/json --
+{"service":{"foo":{"name":"foo","port":7080},"bar":{"name":"bar","port":8000},"baz":{"name":"foobar","port":7080}}}
+-- out/legacy-debug --
+<0>{service: <1>{[]: <2>(Name: string)-><3>{name: (string | *<2>.Name), port: (int | *7080)}, foo: <4>{name: "foo", port: 7080}, bar: <5>{name: "bar", port: 8000}, baz: <6>{name: "foobar", port: 7080}}}
diff --git a/cue/testdata/fulleval/003_field templates.txtar b/cue/testdata/fulleval/003_field templates.txtar
new file mode 100644
index 0000000..c1b9e2a
--- /dev/null
+++ b/cue/testdata/fulleval/003_field templates.txtar
@@ -0,0 +1,96 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: field templates
+#evalFull
+-- in.cue --
+a: {
+	[name=_]: int
+	k:        1
+}
+b: {
+	[X=_]: {x: 0, y: *1 | int}
+	v: {}
+	w: {y: 0}
+}
+b: {[y=_]: {}} // TODO: allow different name
+c: {
+	[Name=_]: {name: Name, y: 1}
+	foo: {}
+	bar: _
+}
+-- out/def --
+a: {
+	{[name=string]: int}
+	k: 1
+}
+b: {
+	{[X=string]: {
+		x: 0, y: *1 | int
+	}}
+	v: {
+		x: 0
+		y: *1 | int
+	}
+	w: {
+		x: 0
+		y: 0
+	}
+}
+c: {
+	{[Name=string]: {
+		y: 1, name: Name
+	}}
+	foo: {
+		y:    1
+		name: "foo"
+	}
+	bar: {
+		y:    1
+		name: "bar"
+	}
+}
+-- out/export --
+a: {
+	k: 1
+}
+b: {
+	v: {
+		x: 0
+		y: 1
+	}
+	w: {
+		x: 0
+		y: 0
+	}
+}
+c: {
+	foo: {
+		y:    1
+		name: "foo"
+	}
+	bar: {
+		y:    1
+		name: "bar"
+	}
+}
+-- out/yaml --
+a:
+  k: 1
+b:
+  v:
+    x: 0
+    y: 1
+  w:
+    x: 0
+    y: 0
+c:
+  foo:
+    y: 1
+    name: foo
+  bar:
+    y: 1
+    name: bar
+-- out/json --
+{"a":{"k":1},"b":{"v":{"x":0,"y":1},"w":{"x":0,"y":0}},"c":{"foo":{"y":1,"name":"foo"},"bar":{"y":1,"name":"bar"}}}
+-- out/legacy-debug --
+<0>{a: <1>{[]: <2>(name: string)->int, k: 1}, b: <3>{[]: <4>(X: string)->(<5>{x: 0, y: (*1 | int)} & <6>{}), v: <7>{x: 0, y: 1}, w: <8>{x: 0, y: 0}}, c: <9>{[]: <10>(Name: string)-><11>{y: 1, name: <10>.Name}, foo: <12>{y: 1, name: "foo"}, bar: <13>{y: 1, name: "bar"}}}
diff --git a/cue/testdata/fulleval/004_field comprehension.txtar b/cue/testdata/fulleval/004_field comprehension.txtar
new file mode 100644
index 0000000..c1a675d
--- /dev/null
+++ b/cue/testdata/fulleval/004_field comprehension.txtar
@@ -0,0 +1,71 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: field comprehension
+#evalFull
+-- in.cue --
+a: {
+	for k, v in b
+	if k < "d"
+	if v > b.a {
+		"\(k)": v
+	}
+}
+b: {
+	a: 1
+	b: 2
+	c: 3
+	d: 4
+}
+c: {
+	for k, v in b
+	if k < "d"
+	if v > b.a {
+		"\(k)": v
+	}
+}
+-- out/def --
+a: {
+	b: 2
+	c: 3
+}
+b: {
+	a: 1
+	b: 2
+	c: 3
+	d: 4
+}
+c: {
+	b: 2
+	c: 3
+}
+-- out/export --
+a: {
+	b: 2
+	c: 3
+}
+b: {
+	a: 1
+	b: 2
+	c: 3
+	d: 4
+}
+c: {
+	b: 2
+	c: 3
+}
+-- out/yaml --
+a:
+  b: 2
+  c: 3
+b:
+  a: 1
+  b: 2
+  c: 3
+  d: 4
+c:
+  b: 2
+  c: 3
+-- out/json --
+{"a":{"b":2,"c":3},"b":{"a":1,"b":2,"c":3,"d":4},"c":{"b":2,"c":3}}
+-- out/legacy-debug --
+<0>{a: <1>{b: 2, c: 3}, b: <2>{a: 1, b: 2, c: 3, d: 4}, c: <3>{b: 2, c: 3}}
diff --git a/cue/testdata/fulleval/005_conditional field.txtar b/cue/testdata/fulleval/005_conditional field.txtar
new file mode 100644
index 0000000..e74c1f2
--- /dev/null
+++ b/cue/testdata/fulleval/005_conditional field.txtar
@@ -0,0 +1,36 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: conditional field
+#evalFull
+-- in.cue --
+
+if b {
+	a: "foo"
+}
+b: true
+c: {
+	a: 3
+	if a > 1 {
+		a: 3
+	}
+}
+d: {
+	a: int
+	if a > 1 {
+		a: 3
+	}
+}
+-- out/def --
+b: true
+a: "foo"
+c: {
+	a: 3
+}
+d: {
+	a: int
+	if a > 1 {
+		a: 3
+	}
+}
+-- out/legacy-debug --
+<0>{b: true, a: "foo", c: <1>{a: 3}, d: <2>{a: int if (<3>.a > 1) yield <4>{a: 3}}}
diff --git a/cue/testdata/fulleval/006_referencing field in field comprehension.txtar b/cue/testdata/fulleval/006_referencing field in field comprehension.txtar
new file mode 100644
index 0000000..66a5a43
--- /dev/null
+++ b/cue/testdata/fulleval/006_referencing field in field comprehension.txtar
@@ -0,0 +1,41 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: referencing field in field comprehension
+#evalFull
+-- in.cue --
+a: {b: c: 4}
+a: {
+	b: d: 5
+	for k, v in b {
+		"\(k)": v
+	}
+}
+-- out/def --
+a: {
+	b: {
+		c: 4
+		d: 5
+	}
+	c: 4
+	d: 5
+}
+-- out/export --
+a: {
+	b: {
+		c: 4
+		d: 5
+	}
+	c: 4
+	d: 5
+}
+-- out/yaml --
+a:
+  b:
+    c: 4
+    d: 5
+  c: 4
+  d: 5
+-- out/json --
+{"a":{"b":{"c":4,"d":5},"c":4,"d":5}}
+-- out/legacy-debug --
+<0>{a: <1>{b: <2>{c: 4, d: 5}, c: 4, d: 5}}
diff --git a/cue/testdata/fulleval/007_different labels for templates.txtar b/cue/testdata/fulleval/007_different labels for templates.txtar
new file mode 100644
index 0000000..d1596bc
--- /dev/null
+++ b/cue/testdata/fulleval/007_different labels for templates.txtar
@@ -0,0 +1,31 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: different labels for templates
+#evalFull
+-- in.cue --
+a: [X=string]: {name: X}
+a: [Name=string]: {name: Name}
+a: foo: {}
+-- out/def --
+a: {
+	{[X=string]: {
+		name: X & X
+	}}
+	foo: {
+		name: "foo"
+	}
+}
+-- out/export --
+a: {
+	foo: {
+		name: "foo"
+	}
+}
+-- out/yaml --
+a:
+  foo:
+    name: foo
+-- out/json --
+{"a":{"foo":{"name":"foo"}}}
+-- out/legacy-debug --
+<0>{a: <1>{[]: <2>(X: string)->(<3>{name: <2>.X} & <4>{name: <2>.X}), foo: <5>{name: "foo"}}}
diff --git a/cue/testdata/fulleval/008_nested templates in one field.txtar b/cue/testdata/fulleval/008_nested templates in one field.txtar
new file mode 100644
index 0000000..9aea5f9
--- /dev/null
+++ b/cue/testdata/fulleval/008_nested templates in one field.txtar
@@ -0,0 +1,106 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: nested templates in one field
+#evalFull
+-- in.cue --
+a: [A=string]: b: [B=string]: {
+	name: A
+	kind: B
+}
+a: "A": b: "B": _
+a: "C": b: "D": _
+a: "EE": b: "FF": {c: "bar"}
+-- out/def --
+a: {
+	{[A=string]: {
+		b: {
+			[B=string]: {
+				name: A, kind: B
+			}
+		}
+	}}
+	A: {
+		b: {
+			{[B=string]: {
+				name: "A", kind: B
+			}}
+			B: {
+				name: "A"
+				kind: "B"
+			}
+		}
+	}
+	C: {
+		b: {
+			{[B=string]: {
+				name: "C", kind: B
+			}}
+			D: {
+				name: "C"
+				kind: "D"
+			}
+		}
+	}
+	EE: {
+		b: {
+			{[B=string]: {
+				name: "EE", kind: B
+			}}
+			FF: {
+				name: "EE"
+				kind: "FF"
+				c:    "bar"
+			}
+		}
+	}
+}
+-- out/export --
+a: {
+	A: {
+		b: {
+			B: {
+				name: "A"
+				kind: "B"
+			}
+		}
+	}
+	C: {
+		b: {
+			D: {
+				name: "C"
+				kind: "D"
+			}
+		}
+	}
+	EE: {
+		b: {
+			FF: {
+				name: "EE"
+				kind: "FF"
+				c:    "bar"
+			}
+		}
+	}
+}
+-- out/yaml --
+a:
+  A:
+    b:
+      B:
+        name: A
+        kind: B
+  C:
+    b:
+      D:
+        name: C
+        kind: D
+  EE:
+    b:
+      FF:
+        name: EE
+        kind: FF
+        c: bar
+-- out/json --
+{"a":{"A":{"b":{"B":{"name":"A","kind":"B"}}},"C":{"b":{"D":{"name":"C","kind":"D"}}},"EE":{"b":{"FF":{"name":"EE","kind":"FF","c":"bar"}}}}}
+-- out/legacy-debug --
+<0>{a: <1>{[]: <2>(A: string)-><3>{b: <4>{[]: <5>(B: string)-><6>{name: <2>.A, kind: <5>.B}, }}, A: <7>{b: <8>{[]: <9>(B: string)-><10>{name: <11>.A, kind: <9>.B}, B: <12>{name: "A", kind: "B"}}}, C: <13>{b: <14>{[]: <15>(B: string)-><16>{name: <17>.A, kind: <15>.B}, D: <18>{name: "C", kind: "D"}}}, EE: <19>{b: <20>{[]: <21>(B: string)-><22>{name: <23>.A, kind: <21>.B}, FF: <24>{name: "EE", kind: "FF", c: "bar"}}}}}
diff --git a/cue/testdata/fulleval/009_template unification within one struct.txtar b/cue/testdata/fulleval/009_template unification within one struct.txtar
new file mode 100644
index 0000000..2cf0f3f
--- /dev/null
+++ b/cue/testdata/fulleval/009_template unification within one struct.txtar
@@ -0,0 +1,64 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: template unification within one struct
+#evalFull
+-- in.cue --
+a: {
+	[A=string]: {name: A}
+	// TODO: allow duplicate alias here
+	[X=string]: {kind: X}
+}
+a: "A": _
+a: "C": _
+a: "E": {c: "bar"}
+-- out/def --
+a: {
+	{[A=string]: {
+		name: A, kind: A
+	}}
+	E: {
+		name: "E"
+		kind: "E"
+		c:    "bar"
+	}
+	A: {
+		name: "A"
+		kind: "A"
+	}
+	C: {
+		name: "C"
+		kind: "C"
+	}
+}
+-- out/export --
+a: {
+	E: {
+		name: "E"
+		kind: "E"
+		c:    "bar"
+	}
+	A: {
+		name: "A"
+		kind: "A"
+	}
+	C: {
+		name: "C"
+		kind: "C"
+	}
+}
+-- out/yaml --
+a:
+  E:
+    name: E
+    kind: E
+    c: bar
+  A:
+    name: A
+    kind: A
+  C:
+    name: C
+    kind: C
+-- out/json --
+{"a":{"E":{"name":"E","kind":"E","c":"bar"},"A":{"name":"A","kind":"A"},"C":{"name":"C","kind":"C"}}}
+-- out/legacy-debug --
+<0>{a: <1>{[]: <2>(A: string)->(<3>{name: <2>.A} & <4>{kind: <2>.A}), E: <5>{name: "E", kind: "E", c: "bar"}, A: <6>{name: "A", kind: "A"}, C: <7>{name: "C", kind: "C"}}}
diff --git a/cue/testdata/fulleval/010_field comprehensions with multiple keys.txtar b/cue/testdata/fulleval/010_field comprehensions with multiple keys.txtar
new file mode 100644
index 0000000..32cc966
--- /dev/null
+++ b/cue/testdata/fulleval/010_field comprehensions with multiple keys.txtar
@@ -0,0 +1,126 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: field comprehensions with multiple keys
+#evalFull
+-- in.cue --
+
+for x in [
+	{a: "A", b: "B"},
+	{a: "C", b: "D"},
+	{a: "E", b: "F"},
+] {
+	a: "\(x.a)": b: "\(x.b)": x
+}
+
+for x in [
+	{a: "A", b: "B"},
+	{a: "C", b: "D"},
+	{a: "E", b: "F"},
+] {
+	"\(x.a)": "\(x.b)": x
+}
+-- out/def --
+E: {
+	F: x
+}
+a: {
+	E: {
+		b: {
+			F: x
+		}
+	}
+	A: {
+		b: {
+			B: x
+		}
+	}
+	C: {
+		b: {
+			D: x
+		}
+	}
+}
+A: {
+	B: x
+}
+C: {
+	D: x
+}
+-- out/export --
+E: {
+	F: {
+		a: "E"
+		b: "F"
+	}
+}
+a: {
+	E: {
+		b: {
+			F: {
+				a: "E"
+				b: "F"
+			}
+		}
+	}
+	A: {
+		b: {
+			B: {
+				a: "A"
+				b: "B"
+			}
+		}
+	}
+	C: {
+		b: {
+			D: {
+				a: "C"
+				b: "D"
+			}
+		}
+	}
+}
+A: {
+	B: {
+		a: "A"
+		b: "B"
+	}
+}
+C: {
+	D: {
+		a: "C"
+		b: "D"
+	}
+}
+-- out/yaml --
+E:
+  F:
+    a: E
+    b: F
+a:
+  E:
+    b:
+      F:
+        a: E
+        b: F
+  A:
+    b:
+      B:
+        a: A
+        b: B
+  C:
+    b:
+      D:
+        a: C
+        b: D
+A:
+  B:
+    a: A
+    b: B
+C:
+  D:
+    a: C
+    b: D
+-- out/json --
+{"E":{"F":{"a":"E","b":"F"}},"a":{"E":{"b":{"F":{"a":"E","b":"F"}}},"A":{"b":{"B":{"a":"A","b":"B"}}},"C":{"b":{"D":{"a":"C","b":"D"}}}},"A":{"B":{"a":"A","b":"B"}},"C":{"D":{"a":"C","b":"D"}}}
+-- out/legacy-debug --
+<0>{E: <1>{F: <2>{a: "E", b: "F"}}, a: <3>{E: <4>{b: <5>{F: <6>{a: "E", b: "F"}}}, A: <7>{b: <8>{B: <9>{a: "A", b: "B"}}}, C: <10>{b: <11>{D: <12>{a: "C", b: "D"}}}}, A: <13>{B: <14>{a: "A", b: "B"}}, C: <15>{D: <16>{a: "C", b: "D"}}}
diff --git a/cue/testdata/fulleval/011_field comprehensions with templates.txtar b/cue/testdata/fulleval/011_field comprehensions with templates.txtar
new file mode 100644
index 0000000..290109d
--- /dev/null
+++ b/cue/testdata/fulleval/011_field comprehensions with templates.txtar
@@ -0,0 +1,57 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: field comprehensions with templates
+#evalFull
+-- in.cue --
+num: 1
+a: {
+	if num < 5 {
+		[A=string]: [B=string]: {
+			name: A
+			kind: B
+		}
+	}
+}
+a: b: c: d: "bar"
+-- out/def --
+num: 1
+a: {
+	{[A=string]: {
+		[B=string]: {
+			name: A, kind: B
+		}
+	}}
+	b: {
+		{[B=string]: {
+			name: "b", kind: B
+		}}
+		c: {
+			name: "b"
+			kind: "c"
+			d:    "bar"
+		}
+	}
+}
+-- out/export --
+num: 1
+a: {
+	b: {
+		c: {
+			name: "b"
+			kind: "c"
+			d:    "bar"
+		}
+	}
+}
+-- out/yaml --
+num: 1
+a:
+  b:
+    c:
+      name: b
+      kind: c
+      d: bar
+-- out/json --
+{"num":1,"a":{"b":{"c":{"name":"b","kind":"c","d":"bar"}}}}
+-- out/legacy-debug --
+<0>{num: 1, a: <1>{[]: <2>(A: string)-><3>{[]: <4>(B: string)-><5>{name: <2>.A, kind: <4>.B}, }, b: <6>{[]: <7>(B: string)-><8>{name: <9>.A, kind: <7>.B}, c: <10>{name: "b", kind: "c", d: "bar"}}}}
diff --git a/cue/testdata/fulleval/012_disjunctions of lists.txtar b/cue/testdata/fulleval/012_disjunctions of lists.txtar
new file mode 100644
index 0000000..8260c5d
--- /dev/null
+++ b/cue/testdata/fulleval/012_disjunctions of lists.txtar
@@ -0,0 +1,15 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: disjunctions of lists
+#evalFull
+-- in.cue --
+l: *[ int, int] | [ string, string]
+
+l1: [ "a", "b"]
+l2: l & [ "c", "d"]
+-- out/def --
+l: *[int, int] | [string, string]
+l1: ["a", "b"]
+l2: ["c", "d"]
+-- out/legacy-debug --
+<0>{l: [int,int], l1: ["a","b"], l2: ["c","d"]}
diff --git a/cue/testdata/fulleval/013_normalization.txtar b/cue/testdata/fulleval/013_normalization.txtar
new file mode 100644
index 0000000..8949992
--- /dev/null
+++ b/cue/testdata/fulleval/013_normalization.txtar
@@ -0,0 +1,14 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: normalization
+#evalFull
+-- in.cue --
+a: string | string
+b: *1 | *int
+c: *1.0 | *float
+-- out/def --
+a: string
+b: int
+c: float
+-- out/legacy-debug --
+<0>{a: string, b: int, c: float}
diff --git a/cue/testdata/fulleval/014_default disambiguation and elimination.txtar b/cue/testdata/fulleval/014_default disambiguation and elimination.txtar
new file mode 100644
index 0000000..a078caf
--- /dev/null
+++ b/cue/testdata/fulleval/014_default disambiguation and elimination.txtar
@@ -0,0 +1,19 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: default disambiguation and elimination
+#evalFull
+-- in.cue --
+a: *1 | int
+b: *3 | int
+c: a & b
+d: b & a
+
+e: *1 | *1
+-- out/def --
+a: *1 | int
+b: *3 | int
+c: a & b
+d: b & a
+e: 1
+-- out/legacy-debug --
+<0>{a: 1, b: 3, c: int, d: int, e: 1}
diff --git a/cue/testdata/fulleval/015_list comprehension.txtar b/cue/testdata/fulleval/015_list comprehension.txtar
new file mode 100644
index 0000000..e1a497c
--- /dev/null
+++ b/cue/testdata/fulleval/015_list comprehension.txtar
@@ -0,0 +1,57 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: list comprehension
+#evalFull
+-- in.cue --
+a: [ for k, v in b if k < "d" if v > b.a {k}]
+b: {
+	a: 1
+	b: 2
+	c: 3
+	d: 4
+}
+c: [ for _, x in b for _, y in b if x < y {x}]
+d: [ for x, _ in a {x}]
+-- out/def --
+a: ["b", "c"]
+b: {
+	a: 1
+	b: 2
+	c: 3
+	d: 4
+}
+c: [1, 1, 1, 2, 2, 3]
+d: [0, 1]
+-- out/export --
+a: ["b", "c"]
+b: {
+	a: 1
+	b: 2
+	c: 3
+	d: 4
+}
+c: [1, 1, 1, 2, 2, 3]
+d: [0, 1]
+-- out/yaml --
+a:
+- b
+- c
+b:
+  a: 1
+  b: 2
+  c: 3
+  d: 4
+c:
+- 1
+- 1
+- 1
+- 2
+- 2
+- 3
+d:
+- 0
+- 1
+-- out/json --
+{"a":["b","c"],"b":{"a":1,"b":2,"c":3,"d":4},"c":[1,1,1,2,2,3],"d":[0,1]}
+-- out/legacy-debug --
+<0>{a: ["b","c"], b: <1>{a: 1, b: 2, c: 3, d: 4}, c: [1,1,1,2,2,3], d: [0,1]}
diff --git a/cue/testdata/fulleval/016_struct comprehension with template.txtar b/cue/testdata/fulleval/016_struct comprehension with template.txtar
new file mode 100644
index 0000000..3676a1d
--- /dev/null
+++ b/cue/testdata/fulleval/016_struct comprehension with template.txtar
@@ -0,0 +1,108 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: struct comprehension with template
+#evalFull
+-- in.cue --
+result: [ for _, v in service {v}]
+
+service: [Name=string]: {
+	name: *Name | string
+	type: "service"
+	port: *7080 | int
+}
+service: foo: {}
+service: bar: {port: 8000}
+service: baz: {name: "foobar"}
+-- out/def --
+result: [{
+	name: *"foo" | string
+	type: "service"
+	port: *7080 | int
+}, {
+	name: *"bar" | string
+	type: "service"
+	port: 8000
+}, {
+	name: "foobar"
+	type: "service"
+	port: *7080 | int
+}]
+service: {
+	{[Name=string]: {
+		name: *Name | string, type: "service", port: *7080 | int
+	}}
+	foo: {
+		name: *"foo" | string
+		type: "service"
+		port: *7080 | int
+	}
+	bar: {
+		name: *"bar" | string
+		type: "service"
+		port: 8000
+	}
+	baz: {
+		name: "foobar"
+		type: "service"
+		port: *7080 | int
+	}
+}
+-- out/export --
+result: [{
+	name: "foo"
+	type: "service"
+	port: 7080
+}, {
+	name: "bar"
+	type: "service"
+	port: 8000
+}, {
+	name: "foobar"
+	type: "service"
+	port: 7080
+}]
+service: {
+	foo: {
+		name: "foo"
+		type: "service"
+		port: 7080
+	}
+	bar: {
+		name: "bar"
+		type: "service"
+		port: 8000
+	}
+	baz: {
+		name: "foobar"
+		type: "service"
+		port: 7080
+	}
+}
+-- out/yaml --
+result:
+- name: foo
+  type: service
+  port: 7080
+- name: bar
+  type: service
+  port: 8000
+- name: foobar
+  type: service
+  port: 7080
+service:
+  foo:
+    name: foo
+    type: service
+    port: 7080
+  bar:
+    name: bar
+    type: service
+    port: 8000
+  baz:
+    name: foobar
+    type: service
+    port: 7080
+-- out/json --
+{"result":[{"name":"foo","type":"service","port":7080},{"name":"bar","type":"service","port":8000},{"name":"foobar","type":"service","port":7080}],"service":{"foo":{"name":"foo","type":"service","port":7080},"bar":{"name":"bar","type":"service","port":8000},"baz":{"name":"foobar","type":"service","port":7080}}}
+-- out/legacy-debug --
+<0>{result: [<1>{name: "foo", type: "service", port: 7080},<2>{name: "bar", type: "service", port: 8000},<3>{name: "foobar", type: "service", port: 7080}], service: <4>{[]: <5>(Name: string)-><6>{name: (*<5>.Name | string), type: "service", port: (*7080 | int)}, foo: <7>{name: "foo", type: "service", port: 7080}, bar: <8>{name: "bar", type: "service", port: 8000}, baz: <9>{name: "foobar", type: "service", port: 7080}}}
diff --git a/cue/testdata/fulleval/017_resolutions in struct comprehension keys.txtar b/cue/testdata/fulleval/017_resolutions in struct comprehension keys.txtar
new file mode 100644
index 0000000..bdc2cff
--- /dev/null
+++ b/cue/testdata/fulleval/017_resolutions in struct comprehension keys.txtar
@@ -0,0 +1,21 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: resolutions in struct comprehension keys
+#evalFull
+-- in.cue --
+a: {for _, b in ["c"] {"\(b+".")": "a"}}
+-- out/def --
+a: {
+	"c.": "a"
+}
+-- out/export --
+a: {
+	"c.": "a"
+}
+-- out/yaml --
+a:
+  c.: a
+-- out/json --
+{"a":{"c.":"a"}}
+-- out/legacy-debug --
+<0>{a: <1>{"c.": "a"}}
diff --git a/cue/testdata/fulleval/018_recursive evaluation within list.txtar b/cue/testdata/fulleval/018_recursive evaluation within list.txtar
new file mode 100644
index 0000000..425efde
--- /dev/null
+++ b/cue/testdata/fulleval/018_recursive evaluation within list.txtar
@@ -0,0 +1,36 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: recursive evaluation within list
+#evalFull
+-- in.cue --
+l: [a]
+a: b & {c: "t"}
+b: {
+	d: c
+	c: string
+}
+l1: [a1]
+a1: b1 & {c: "t"}
+b1: {
+	d: "s" + c
+	c: string
+}
+-- out/def --
+l: [a]
+a: b & {
+	c: "t"
+}
+b: {
+	c: string
+	d: c
+}
+l1: [a1]
+a1: b1 & {
+	c: "t"
+}
+b1: {
+	c: string
+	d: "s" + c
+}
+-- out/legacy-debug --
+<0>{l: [<1>{c: "t", d: "t"}], a: <2>{c: "t", d: "t"}, b: <3>{c: string, d: string}, l1: [<4>{c: "t", d: "st"}], a1: <5>{c: "t", d: "st"}, b1: <6>{c: string, d: ("s" + <7>.c)}}
diff --git a/cue/testdata/fulleval/019_ips.txtar b/cue/testdata/fulleval/019_ips.txtar
new file mode 100644
index 0000000..6081e4f
--- /dev/null
+++ b/cue/testdata/fulleval/019_ips.txtar
@@ -0,0 +1,22 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: ips
+#evalFull
+-- in.cue --
+IP: 4 * [ uint8]
+
+Private:
+	*[ 192, 168, uint8, uint8] |
+	[ 10, uint8, uint8, uint8] |
+	[ 172, >=16 & <=32, uint8, uint8]
+
+Inst: Private & [ _, 10, ...]
+
+MyIP: Inst & [_, _, 10, 10]
+-- out/def --
+IP: [uint8, uint8, uint8, uint8]
+Private: *[192, 168, uint8, uint8] | [10, uint8, uint8, uint8] | [172, >=16 & <=32, uint8, uint8]
+Inst: [10, 10, uint8, uint8]
+MyIP: [10, 10, 10, 10]
+-- out/legacy-debug --
+<0>{IP: [(int & >=0 & int & <=255),(int & >=0 & int & <=255),(int & >=0 & int & <=255),(int & >=0 & int & <=255)], Private: [192,168,(int & >=0 & int & <=255),(int & >=0 & int & <=255)], Inst: [10,10,(int & >=0 & int & <=255),(int & >=0 & int & <=255)], MyIP: [10,10,10,10]}
diff --git a/cue/testdata/fulleval/020_complex interaction of groundness.txtar b/cue/testdata/fulleval/020_complex interaction of groundness.txtar
new file mode 100644
index 0000000..da525a4
--- /dev/null
+++ b/cue/testdata/fulleval/020_complex interaction of groundness.txtar
@@ -0,0 +1,30 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: complex interaction of groundness
+#evalFull
+-- in.cue --
+res: [ for x in a for y in x {y & {d: "b"}}]
+res: [ a.b.c & {d: "b"}]
+
+a: b: [C=string]: {d: string, s: "a" + d}
+a: b: c: d: string
+-- out/def --
+res: [{
+	d: "b"
+	s: "ab"
+} & (a.b.c & {
+	d: "b"
+})]
+a: {
+	b: {
+		{[C=string]: {
+			d: string, s: "a" + d
+		}}
+		c: {
+			d: string
+			s: "a" + d
+		}
+	}
+}
+-- out/legacy-debug --
+<0>{res: [<1>{d: "b", s: "ab"}], a: <2>{b: <3>{[]: <4>(C: string)-><5>{d: string, s: ("a" + <5>.d)}, c: <6>{d: string, s: ("a" + <7>.d)}}}}
diff --git a/cue/testdata/fulleval/021_complex groundness 2.txtar b/cue/testdata/fulleval/021_complex groundness 2.txtar
new file mode 100644
index 0000000..67bf004
--- /dev/null
+++ b/cue/testdata/fulleval/021_complex groundness 2.txtar
@@ -0,0 +1,35 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: complex groundness 2
+#evalFull
+-- in.cue --
+r1: f1 & {y: "c"}
+
+f1: {y: string, res: a.b.c & {d: y}}
+
+a: b: c: {d: string, s: "a" + d}
+a: b: [C=string]: {d: string, s: "a" + d}
+a: b: c: d: string
+-- out/def --
+r1: f1 & {
+	y: "c"
+}
+f1: {
+	y:   string
+	res: a.b.c & {
+		d: y
+	}
+}
+a: {
+	b: {
+		{[C=string]: {
+			d: string, s: "a" + d
+		}}
+		c: {
+			d: string
+			s: "a"+d & "a"+d
+		}
+	}
+}
+-- out/legacy-debug --
+<0>{r1: <1>{y: "c", res: <2>{d: "c", s: "ac"}}, f1: <3>{y: string, res: <4>{d: string, s: (("a" + <5>.d) & ("a" + <5>.d))}}, a: <6>{b: <7>{[]: <8>(C: string)-><9>{d: string, s: ("a" + <9>.d)}, c: <10>{d: string, s: (("a" + <11>.d) & ("a" + <11>.d))}}}}
diff --git a/cue/testdata/fulleval/022_references from template to concrete.txtar b/cue/testdata/fulleval/022_references from template to concrete.txtar
new file mode 100644
index 0000000..aa6c93c
--- /dev/null
+++ b/cue/testdata/fulleval/022_references from template to concrete.txtar
@@ -0,0 +1,64 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: references from template to concrete
+#evalFull
+-- in.cue --
+res: [t]
+t: [X=string]: {
+	a: c + b.str
+	b: str: string
+	c: "X"
+}
+t: x: {b: str: "DDDD"}
+-- out/def --
+res: [t]
+t: {
+	{[X=string]: {
+		a: c + b.str, c: "X", b: {
+			str:          string
+		}
+	}}
+	x: {
+		a: "XDDDD"
+		c: "X"
+		b: {
+			str: "DDDD"
+		}
+	}
+}
+-- out/export --
+res: [{
+	x: {
+		a: "XDDDD"
+		c: "X"
+		b: {
+			str: "DDDD"
+		}
+	}
+}]
+t: {
+	x: {
+		a: "XDDDD"
+		c: "X"
+		b: {
+			str: "DDDD"
+		}
+	}
+}
+-- out/yaml --
+res:
+- x:
+    a: XDDDD
+    c: X
+    b:
+      str: DDDD
+t:
+  x:
+    a: XDDDD
+    c: X
+    b:
+      str: DDDD
+-- out/json --
+{"res":[{"x":{"a":"XDDDD","c":"X","b":{"str":"DDDD"}}}],"t":{"x":{"a":"XDDDD","c":"X","b":{"str":"DDDD"}}}}
+-- out/legacy-debug --
+<0>{res: [<1>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <5>{a: "XDDDD", c: "X", b: <6>{str: "DDDD"}}}], t: <7>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <8>{a: "XDDDD", c: "X", b: <9>{str: "DDDD"}}}}
diff --git a/cue/testdata/fulleval/023_reentrance.txtar b/cue/testdata/fulleval/023_reentrance.txtar
new file mode 100644
index 0000000..1b9ab5a
--- /dev/null
+++ b/cue/testdata/fulleval/023_reentrance.txtar
@@ -0,0 +1,48 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: reentrance
+#evalFull
+-- in.cue --
+// This indirection is needed to avoid binding references to fib
+// within fib to the instantiated version.
+fibRec: {nn: int, out: (fib & {n: nn}).out}
+fib: {
+	n: int
+
+	if n >= 2 {
+		out: (fibRec & {nn: n - 2}).out + (fibRec & {nn: n - 1}).out
+	}
+	if n < 2 {
+		out: n
+	}
+}
+fib2:  (fib & {n: 2}).out
+fib7:  (fib & {n: 7}).out
+fib12: (fib & {n: 12}).out
+-- out/def --
+// This indirection is needed to avoid binding references to fib
+// within fib to the instantiated version.
+fibRec: {
+	nn:  int
+	out: (fib & {
+		n: nn
+	}).out
+}
+fib: {
+	n: int
+	if n >= 2 {
+		out: (fibRec & {
+			nn: n - 2
+		}).out + (fibRec & {
+			nn: n - 1
+		}).out
+	}
+	if n < 2 {
+		out: n
+	}
+}
+fib2:  1
+fib7:  13
+fib12: 144
+-- out/legacy-debug --
+<0>{fibRec: <1>{nn: int, out: (<2>.fib & <3>{n: <4>.nn}).out}, fib: <5>{n: int if (<6>.n >= 2) yield <7>{out: ((<2>.fibRec & <8>{nn: (<6>.n - 2)}).out + (<2>.fibRec & <9>{nn: (<6>.n - 1)}).out)},  if (<6>.n < 2) yield <10>{out: <6>.n}}, fib2: 1, fib7: 13, fib12: 144}
diff --git "a/cue/testdata/fulleval/024_Issue \04323.txtar" "b/cue/testdata/fulleval/024_Issue \04323.txtar"
new file mode 100644
index 0000000..5f12158
--- /dev/null
+++ "b/cue/testdata/fulleval/024_Issue \04323.txtar"
@@ -0,0 +1,16 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: Issue #23
+#evalFull
+-- in.cue --
+x: {a:     1} | {a: 2}
+y: x & {a: 3}
+-- out/def --
+x: {
+	a: 1
+} | {
+	a: 2
+}
+y: _|_ // ; empty disjunction: conflicting values 2 and 3
+-- out/legacy-debug --
+<0>{x: (<1>{a: 1} | <2>{a: 2}), y: _|_((1 & 3):empty disjunction: conflicting values 1 and 3;(2 & 3):empty disjunction: conflicting values 2 and 3)}
diff --git a/cue/testdata/fulleval/025_cannot resolve references that would be ambiguous.txtar b/cue/testdata/fulleval/025_cannot resolve references that would be ambiguous.txtar
new file mode 100644
index 0000000..68b5eba
--- /dev/null
+++ b/cue/testdata/fulleval/025_cannot resolve references that would be ambiguous.txtar
@@ -0,0 +1,34 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: cannot resolve references that would be ambiguous
+#evalFull
+-- in.cue --
+a1: *0 | 1
+a1: a3 - a2
+a2: *0 | 1
+a2: a3 - a1
+a3: 1
+
+b1: (*0 | 1) & b2
+b2: (0 | *1) & b1
+
+c1: (*{a: 1} | {b: 1}) & c2
+c2: (*{a: 2} | {b: 2}) & c1
+-- out/def --
+a1: (*0 | 1) & a3-a2
+a3: 1
+a2: (*0 | 1) & a3-a1
+b1: (*0 | 1) & b2
+b2: (0 | *1) & b1
+c1: (*{
+	a: 1
+} | {
+	b: 1
+}) & c2
+c2: (*{
+	a: 2
+} | {
+	b: 2
+}) & c1
+-- out/legacy-debug --
+<0>{a1: ((*0 | 1) & (<1>.a3 - <1>.a2)), a3: 1, a2: ((*0 | 1) & (<1>.a3 - <1>.a1)), b1: (0 | 1), b2: (0 | 1), c1: (<2>{a: 1, b: 2} | <3>{a: 2, b: 1}), c2: (<4>{a: 2, b: 1} | <5>{a: 1, b: 2})}
diff --git "a/cue/testdata/fulleval/026_don\047t convert incomplete errors to non-incomplete.txtar" "b/cue/testdata/fulleval/026_don\047t convert incomplete errors to non-incomplete.txtar"
new file mode 100644
index 0000000..9ffbc9c
--- /dev/null
+++ "b/cue/testdata/fulleval/026_don\047t convert incomplete errors to non-incomplete.txtar"
@@ -0,0 +1,46 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: don't convert incomplete errors to non-incomplete
+#evalFull
+-- in.cue --
+import "strings"
+
+n1: {min: <max, max: >min}
+n2: -num
+n3: +num
+n4: num + num
+n5: num - num
+n6: num * num
+n7: num / num
+
+b1: !is
+
+s1: "\(str)"
+s2: strings.ContainsAny("dd")
+s3: strings.ContainsAny(str, "dd")
+
+str: string
+num: <4
+is:  bool
+-- out/def --
+import "strings"
+
+n1: {
+	min: <max
+	max: >min
+}
+n2:  -num
+num: <4
+n3:  +num
+n4:  num + num
+n5:  num - num
+n6:  num * num
+n7:  num / num
+b1:  !is
+is:  bool
+s1:  "\(str)"
+str: string
+s2:  strings.ContainsAny("dd")
+s3:  strings.ContainsAny(str, "dd")
+-- out/legacy-debug --
+<0>{n1: <1>{min: <<2>.max, max: ><2>.min}, n2: -<3>.num, num: <4, n3: +<3>.num, n4: (<3>.num + <3>.num), n5: (<3>.num - <3>.num), n6: (<3>.num * <3>.num), n7: (<3>.num / <3>.num), b1: !<3>.is, is: bool, s1: ""+<3>.str+"", str: string, s2: strings.ContainsAny ("dd"), s3: <4>.ContainsAny (<3>.str,"dd")}
diff --git a/cue/testdata/fulleval/027_len of incomplete types.txtar b/cue/testdata/fulleval/027_len of incomplete types.txtar
new file mode 100644
index 0000000..5fe7a7c
--- /dev/null
+++ b/cue/testdata/fulleval/027_len of incomplete types.txtar
@@ -0,0 +1,34 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: len of incomplete types
+#evalFull
+-- in.cue --
+args: *[] | [...string]
+v1:   len(args)
+v2:   len([])
+v3:   len({})
+v4:   len({a: 3})
+v5:   len({a: 3} | {a: 4})
+v6:   len('sf' | 'dd')
+v7:   len([2] | *[1, 2])
+v8:   len([2] | [1, 2])
+v9:   len("😂")
+v10:  len("")
+-- out/def --
+args: *[] | [...string]
+v1:   0
+v2:   0
+v3:   0
+v4:   1
+v5:   len({
+	a: 3
+} | {
+	a: 4
+})
+v6:  len('sf' | 'dd')
+v7:  2
+v8:  len([2] | [1, 2])
+v9:  4
+v10: 0
+-- out/legacy-debug --
+<0>{args: [], v1: 0, v2: 0, v3: 0, v4: 1, v5: len ((<1>{a: 3} | <2>{a: 4})), v6: len (('sf' | 'dd')), v7: 2, v8: len (([2] | [1,2])), v9: 4, v10: 0}
diff --git a/cue/testdata/fulleval/028_slice rewrite bug.txtar b/cue/testdata/fulleval/028_slice rewrite bug.txtar
new file mode 100644
index 0000000..93c73f9
--- /dev/null
+++ b/cue/testdata/fulleval/028_slice rewrite bug.txtar
@@ -0,0 +1,40 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: slice rewrite bug
+#evalFull
+-- in.cue --
+fn: {
+	arg: [...int] & [1]
+	out: arg[1:]
+}
+fn1: fn & {arg: [1]}
+-- out/def --
+fn: {
+	arg: [1]
+	out: []
+}
+fn1: fn & {
+	arg: [1]
+}
+-- out/export --
+fn: {
+	arg: [1]
+	out: []
+}
+fn1: {
+	arg: [1]
+	out: []
+}
+-- out/yaml --
+fn:
+  arg:
+  - 1
+  out: []
+fn1:
+  arg:
+  - 1
+  out: []
+-- out/json --
+{"fn":{"arg":[1],"out":[]},"fn1":{"arg":[1],"out":[]}}
+-- out/legacy-debug --
+<0>{fn: <1>{arg: [1], out: []}, fn1: <2>{arg: [1], out: []}}
diff --git "a/cue/testdata/fulleval/029_Issue \04394.txtar" "b/cue/testdata/fulleval/029_Issue \04394.txtar"
new file mode 100644
index 0000000..f05a453
--- /dev/null
+++ "b/cue/testdata/fulleval/029_Issue \04394.txtar"
@@ -0,0 +1,55 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: Issue #94
+#evalFull
+-- in.cue --
+foo: {
+	opt?:    1
+	"txt":   2
+	def ::   3
+	regular: 4
+	_hidden: 5
+}
+comp: {for k, v in foo {"\(k)": v}}
+select: {
+	opt:     foo.opt
+	"txt":   foo.txt
+	def ::   foo.def
+	regular: foo.regular
+	_hidden: foo._hidden
+}
+index: {
+	opt:     foo["opt"]
+	"txt":   foo["txt"]
+	def ::   foo["def"]
+	regular: foo["regular"]
+	_hidden: foo["_hidden"]
+}
+-- out/def --
+foo: {
+	opt?:    1
+	txt:     2
+	def ::   3
+	regular: 4
+	_hidden: 5
+}
+comp: {
+	txt:     2
+	regular: 4
+}
+select: {
+	opt:     foo.opt
+	txt:     2
+	def ::   3
+	regular: 4
+	_hidden: 5
+}
+index: {
+	opt:     foo["opt"]
+	txt:     2
+	def ::   _|_ // field "def" is a definition
+	regular: 4
+	_hidden: foo["_hidden"]
+}
+-- out/legacy-debug --
+<0>{foo: <1>{opt?: 1, txt: 2, def :: 3, regular: 4, _hidden: 5}, comp: <2>{txt: 2, regular: 4}, select: <3>{opt: <4>.foo.opt, txt: 2, def :: 3, regular: 4, _hidden: 5}, index: <5>{opt: <4>.foo["opt"], txt: 2, def :: _|_(<4>.foo["def"]:field "def" is a definition), regular: 4, _hidden: <4>.foo["_hidden"]}}
diff --git a/cue/testdata/fulleval/030_retain references with interleaved embedding.txtar b/cue/testdata/fulleval/030_retain references with interleaved embedding.txtar
new file mode 100644
index 0000000..a5cc8b4
--- /dev/null
+++ b/cue/testdata/fulleval/030_retain references with interleaved embedding.txtar
@@ -0,0 +1,52 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: retain references with interleaved embedding
+#evalFull
+-- in.cue --
+a: d: {
+	base
+	info :: {...}
+	Y: info.X
+}
+
+base :: {
+	info :: {...}
+}
+
+a: [Name=string]: {info :: {
+	X: "foo"
+}}
+-- out/def --
+a: {
+	{[Name=string]: {
+		info :: {
+			X: "foo"
+		}
+	}}
+	d: {
+		info :: {
+			...
+		}
+		Y: info.X
+		base
+	}
+}
+base :: {
+	info :: {
+		...
+	}
+}
+-- out/export --
+a: {
+	d: {
+		Y: "foo"
+	}
+}
+-- out/yaml --
+a:
+  d:
+    Y: foo
+-- out/json --
+{"a":{"d":{"Y":"foo"}}}
+-- out/legacy-debug --
+<0>{a: <1>{[]: <2>(Name: string)-><3>{info :: <4>C{X: "foo"}}, d: <5>C{info :: <6>C{X: "foo"}, Y: "foo"}}, base :: <7>C{info :: <8>{...}}}
diff --git a/cue/testdata/fulleval/031_comparison against bottom.txtar b/cue/testdata/fulleval/031_comparison against bottom.txtar
new file mode 100644
index 0000000..820f8f5
--- /dev/null
+++ b/cue/testdata/fulleval/031_comparison against bottom.txtar
@@ -0,0 +1,31 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: comparison against bottom
+#evalFull
+-- in.cue --
+a: _|_ == _|_
+b: err == 1 & 2 // not a literal error, so not allowed
+c: err == _|_   // allowed
+d: err != _|_   // allowed
+e: err != 1 & 3
+// z: err == err // TODO: should infer to be true?
+f: ({a:        1} & {a: 2}) == _|_
+g: ({a:        1} & {b: 2}) == _|_
+h: _|_ == ({a: 1} & {a: 2})
+i: _|_ == ({a: 1} & {b: 2})
+
+err: 1 & 2
+-- out/def --
+a:   true
+b:   _|_ // conflicting values 1 and 2
+err: _|_ // conflicting values 1 and 2
+c:   true
+d:   false
+e:   _|_ // conflicting values 1 and 2
+// z: err == err // TODO: should infer to be true?
+f: true
+g: false
+h: true
+i: false
+-- out/legacy-debug --
+<0>{a: true, b: _|_((1 & 2):conflicting values 1 and 2), err: _|_((1 & 2):conflicting values 1 and 2), c: true, d: false, e: _|_((1 & 2):conflicting values 1 and 2), f: true, g: false, h: true, i: false}
diff --git a/cue/testdata/fulleval/032_or builtin should not fail on non-concrete empty list.txtar b/cue/testdata/fulleval/032_or builtin should not fail on non-concrete empty list.txtar
new file mode 100644
index 0000000..2ab4f21
--- /dev/null
+++ b/cue/testdata/fulleval/032_or builtin should not fail on non-concrete empty list.txtar
@@ -0,0 +1,43 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: or builtin should not fail on non-concrete empty list
+#evalFull
+-- in.cue --
+Workflow :: {
+	jobs: {
+		[jobID=string]: {
+		}
+	}
+	JobID :: or([ for k, _ in jobs {k}])
+}
+
+foo: Workflow & {
+	jobs: foo: {
+	}
+}
+-- out/def --
+Workflow :: {
+	jobs: {
+		[jobID=string]: {}
+	}
+	JobID :: or([ for k, _ in jobs { k } ])
+}
+foo: Workflow & {
+	jobs: {
+		foo: {}
+	}
+}
+-- out/export --
+foo: {
+	jobs: {
+		foo: {}
+	}
+}
+-- out/yaml --
+foo:
+  jobs:
+    foo: {}
+-- out/json --
+{"foo":{"jobs":{"foo":{}}}}
+-- out/legacy-debug --
+<0>{Workflow :: <1>C{jobs: <2>{[]: <3>(jobID: string)-><4>C{}, }, JobID :: or ([ <5>for k, _ in <6>.jobs yield <5>.k ])}, foo: <7>C{jobs: <8>{[]: <9>(jobID: string)-><10>C{}, foo: <11>C{}}, JobID :: "foo"}}
diff --git "a/cue/testdata/fulleval/033_Issue \043153.txtar" "b/cue/testdata/fulleval/033_Issue \043153.txtar"
new file mode 100644
index 0000000..778cd79
--- /dev/null
+++ "b/cue/testdata/fulleval/033_Issue \043153.txtar"
@@ -0,0 +1,38 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: Issue #153
+#evalFull
+-- in.cue --
+Foo: {
+	listOfCloseds: [...Closed]
+}
+
+Closed :: {
+	a: int | *0
+}
+
+Junk: {
+	b: 2
+}
+
+Foo & {
+	listOfCloseds: [{
+		for k, v in Junk {
+			"\(k)": v
+		}
+	}]
+}
+-- out/def --
+Foo: {
+	listOfCloseds: [...Closed]
+}
+listOfCloseds: [_|_, // field "b" not allowed in closed struct
+]
+Closed :: {
+	a: int | *0
+}
+Junk: {
+	b: 2
+}
+-- out/legacy-debug --
+<0>{<1>{listOfCloseds: [_|_(<2>.v:field "b" not allowed in closed struct)]}, Foo: <3>{listOfCloseds: []}, Closed :: <4>C{a: 0}, Junk: <5>{b: 2}}
diff --git a/cue/testdata/fulleval/034_label and field aliases.txtar b/cue/testdata/fulleval/034_label and field aliases.txtar
new file mode 100644
index 0000000..71be1b6
--- /dev/null
+++ b/cue/testdata/fulleval/034_label and field aliases.txtar
@@ -0,0 +1,45 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: label and field aliases
+#evalFull
+-- in.cue --
+p: [ID=string]: {name: ID}
+A="foo=bar": "str"
+a:           A
+B=bb:        4
+b1:          B
+b1:          bb
+C="\(a)":    5
+c:           C
+-- out/def --
+p: {
+	[ID=string]: {
+		name: ID
+	}
+}
+"foo=bar": "str"
+a:         "str"
+bb:        4
+b1:        4
+c:         5
+str:       5
+-- out/export --
+p: {}
+"foo=bar": "str"
+a:         "str"
+bb:        4
+b1:        4
+c:         5
+str:       5
+-- out/yaml --
+p: {}
+foo=bar: str
+a: str
+bb: 4
+b1: 4
+c: 5
+str: 5
+-- out/json --
+{"p":{},"foo=bar":"str","a":"str","bb":4,"b1":4,"c":5,"str":5}
+-- out/legacy-debug --
+<0>{p: <1>{[]: <2>(ID: string)-><3>{name: <2>.ID}, }, "foo=bar": "str", a: "str", bb: 4, b1: 4, c: 5, str: 5}
diff --git a/cue/testdata/fulleval/035_optionals with label fiters.txtar b/cue/testdata/fulleval/035_optionals with label fiters.txtar
new file mode 100644
index 0000000..eef1089
--- /dev/null
+++ b/cue/testdata/fulleval/035_optionals with label fiters.txtar
@@ -0,0 +1,53 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: optionals with label fiters
+#evalFull
+-- in.cue --
+JobID :: =~"^[a-zA-Z]*$"
+Job :: {
+	name: string
+	cmd:  string
+}
+Jobs :: {
+	[JobID]: Job
+	[=~"Test$"]: name: =~"^test" // Must work without ...
+}
+
+jobs: foo: name: "allGood"
+jobs: foo: name: "allGood"
+
+jobs1:          Jobs
+jobs1: foo1: {} // faulty
+
+jobs2: Jobs
+jobs2: fooTest: name: "badName" // faulty
+
+jobs3: Jobs
+jobs3: [string]: Job
+jobs3: fooTest1: name: "badName" // faulty
+-- out/def --
+JobID :: =~"^[a-zA-Z]*$"
+Job :: {
+	name: string
+	cmd:  string
+}
+Jobs :: {
+	{[JobID]: Job}
+	{[=~"Test$"]: {
+		name: =~"^test"
+	}}
+}
+jobs: {
+	foo: {
+		name: "allGood"
+	}
+}
+jobs1: _|_ // field "foo1" not allowed in closed struct
+jobs2: Jobs & {
+	fooTest: {
+		name: "badName"
+	}
+}
+jobs3: _|_ // field "fooTest1" not allowed in closed struct
+-- out/legacy-debug --
+<0>{JobID :: =~"^[a-zA-Z]*$", Job :: <1>C{name: string, cmd: string}, Jobs :: <2>C{[=~"^[a-zA-Z]*$"]: <3>(_: string)-><4>.Job, [=~"Test$"]: <5>(_: string)-><6>C{name: =~"^test"}, }, jobs: <7>{foo: <8>{name: "allGood"}}, jobs1: _|_(<9>{}:field "foo1" not allowed in closed struct), jobs2: <10>C{[=~"^[a-zA-Z]*$"]: <11>(_: string)-><4>.Job, [=~"Test$"]: <12>(_: string)-><13>C{name: =~"^test"}, fooTest: _|_(string:field "cmd" not allowed in closed struct)}, jobs3: _|_(<14>{name: "badName"}:field "fooTest1" not allowed in closed struct)}
diff --git a/cue/testdata/fulleval/036_optionals in open structs.txtar b/cue/testdata/fulleval/036_optionals in open structs.txtar
new file mode 100644
index 0000000..5fded3b
--- /dev/null
+++ b/cue/testdata/fulleval/036_optionals in open structs.txtar
@@ -0,0 +1,41 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: optionals in open structs
+#evalFull
+-- in.cue --
+A: {
+	[=~"^[a-s]*$"]: int
+}
+B: {
+	[=~"^[m-z]*$"]: int
+}
+C :: {A & B}
+c: C & {aaa: 3}
+-- out/def --
+A: {
+	[=~"^[a-s]*$"]: int
+}
+B: {
+	[=~"^[m-z]*$"]: int
+}
+C :: {
+	A & B
+}
+c: C & {
+	aaa: 3
+}
+-- out/export --
+A: {}
+B: {}
+c: {
+	aaa: 3
+}
+-- out/yaml --
+A: {}
+B: {}
+c:
+  aaa: 3
+-- out/json --
+{"A":{},"B":{},"c":{"aaa":3}}
+-- out/legacy-debug --
+<0>{A: <1>{[=~"^[a-s]*$"]: <2>(_: string)->int, }, B: <3>{[=~"^[m-z]*$"]: <4>(_: string)->int, }, C :: <5>C{[=~"^[a-s]*$"]: <6>(_: string)->int, [=~"^[m-z]*$"]: <7>(_: string)->int, }, c: <8>C{[=~"^[a-s]*$"]: <9>(_: string)->int, [=~"^[m-z]*$"]: <10>(_: string)->int, aaa: 3}}
diff --git a/cue/testdata/fulleval/037_conjunction of optional sets.txtar b/cue/testdata/fulleval/037_conjunction of optional sets.txtar
new file mode 100644
index 0000000..1679797
--- /dev/null
+++ b/cue/testdata/fulleval/037_conjunction of optional sets.txtar
@@ -0,0 +1,32 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: conjunction of optional sets
+#evalFull
+-- in.cue --
+A :: {
+	[=~"^[a-s]*$"]: int
+}
+B :: {
+	[=~"^[m-z]*$"]: int
+}
+
+C :: A & B
+c:   C & {aaa: 3}
+
+D :: {A & B}
+d: D & {aaa: 3}
+-- out/def --
+A :: {
+	[=~"^[a-s]*$"]: int
+}
+B :: {
+	[=~"^[m-z]*$"]: int
+}
+C :: A & B
+c:   _|_ // field "aaa" not allowed in closed struct
+D :: {
+	A & B
+}
+d: _|_ // field "aaa" not allowed in closed struct
+-- out/legacy-debug --
+<0>{A :: <1>C{[=~"^[a-s]*$"]: <2>(_: string)->int, }, B :: <3>C{[=~"^[m-z]*$"]: <4>(_: string)->int, }, C :: <5>C{(C{[=~"^[a-s]*$"]: <6>(_: string)->int} & C{[=~"^[m-z]*$"]: <7>(_: string)->int}), }, c: _|_(3:field "aaa" not allowed in closed struct), D :: <8>C{(C{[=~"^[a-s]*$"]: <9>(_: string)->int} & C{[=~"^[m-z]*$"]: <10>(_: string)->int}), }, d: _|_(3:field "aaa" not allowed in closed struct)}
diff --git a/cue/testdata/fulleval/038_continue recursive closing for optionals.txtar b/cue/testdata/fulleval/038_continue recursive closing for optionals.txtar
new file mode 100644
index 0000000..4784ad6
--- /dev/null
+++ b/cue/testdata/fulleval/038_continue recursive closing for optionals.txtar
@@ -0,0 +1,24 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: continue recursive closing for optionals
+#evalFull
+-- in.cue --
+S :: {
+	[string]: {a: int}
+}
+a: S & {
+	v: {b: int}
+}
+-- out/def --
+S :: {
+	[string]: {
+		a: int
+	}
+}
+a: S & {
+	v: {
+		b: int
+	}
+}
+-- out/legacy-debug --
+<0>{S :: <1>{[]: <2>(_: string)-><3>C{a: int}, }, a: <4>{[]: <5>(_: string)-><6>C{a: int}, v: _|_(int:field "b" not allowed in closed struct)}}
diff --git a/cue/testdata/fulleval/039_augment closed optionals.txtar b/cue/testdata/fulleval/039_augment closed optionals.txtar
new file mode 100644
index 0000000..2bc1433
--- /dev/null
+++ b/cue/testdata/fulleval/039_augment closed optionals.txtar
@@ -0,0 +1,58 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: augment closed optionals
+#evalFull
+-- in.cue --
+A :: {
+	[=~"^[a-s]*$"]: int
+}
+B :: {
+	[=~"^[m-z]*?"]: int
+}
+C :: {
+	A & B
+	[=~"^Q*$"]: int
+}
+c: C & {QQ: 3}
+D :: {
+	A
+	B
+}
+d: D & {aaa: 4}
+-- out/def --
+A :: {
+	[=~"^[a-s]*$"]: int
+}
+B :: {
+	[=~"^[m-z]*?"]: int
+}
+C :: {
+	{[=~"^Q*$"]: int}
+	A & B
+}
+c: C & {
+	QQ: 3
+}
+D :: {
+	A
+	B
+}
+d: D & {
+	aaa: 4
+}
+-- out/export --
+c: {
+	QQ: 3
+}
+d: {
+	aaa: 4
+}
+-- out/yaml --
+c:
+  QQ: 3
+d:
+  aaa: 4
+-- out/json --
+{"c":{"QQ":3},"d":{"aaa":4}}
+-- out/legacy-debug --
+<0>{A :: <1>C{[=~"^[a-s]*$"]: <2>(_: string)->int, }, B :: <3>C{[=~"^[m-z]*?"]: <4>(_: string)->int, }, C :: <5>C{C{[=~"^Q*$"]: <6>(_: string)->int}, C{(C{[=~"^[a-s]*$"]: <7>(_: string)->int} & C{[=~"^[m-z]*?"]: <8>(_: string)->int})}, }, c: <9>C{C{[=~"^Q*$"]: <10>(_: string)->int}, C{(C{[=~"^[a-s]*$"]: <11>(_: string)->int} & C{[=~"^[m-z]*?"]: <12>(_: string)->int})}, QQ: 3}, D :: <13>C{[=~"^[a-s]*$"]: <14>(_: string)->int, [=~"^[m-z]*?"]: <15>(_: string)->int, }, d: <16>C{[=~"^[a-s]*$"]: <17>(_: string)->int, [=~"^[m-z]*?"]: <18>(_: string)->int, aaa: 4}}
diff --git a/cue/testdata/fulleval/040.txtar b/cue/testdata/fulleval/040.txtar
new file mode 100644
index 0000000..dc24e55
--- /dev/null
+++ b/cue/testdata/fulleval/040.txtar
@@ -0,0 +1,49 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#evalFull
+-- in.cue --
+Task :: {
+	{
+		op:          "pull"
+		tag:         *"latest" | string
+		refToTag:    tag
+		tagExpr:     tag + "dd"
+		tagInString: "\(tag)"
+	} | {
+		op: "scratch"
+	}
+}
+
+foo: Task & {"op": "pull"}
+-- out/def --
+Task :: {
+	op:          "pull"
+	tag:         *"latest" | string
+	refToTag:    tag
+	tagExpr:     "latestdd"
+	tagInString: "latest"
+} | {
+	op: "scratch"
+}
+foo: Task & {
+	op: "pull"
+}
+-- out/export --
+foo: {
+	op:          "pull"
+	tag:         "latest"
+	refToTag:    "latest"
+	tagExpr:     "latestdd"
+	tagInString: "latest"
+}
+-- out/yaml --
+foo:
+  op: pull
+  tag: latest
+  refToTag: latest
+  tagExpr: latestdd
+  tagInString: latest
+-- out/json --
+{"foo":{"op":"pull","tag":"latest","refToTag":"latest","tagExpr":"latestdd","tagInString":"latest"}}
+-- out/legacy-debug --
+<0>{Task :: (<1>C{op: "pull", tag: (*"latest" | string), refToTag: <1>.tag, tagExpr: (<1>.tag + "dd"), tagInString: ""+<1>.tag+""} | <2>C{op: "scratch"}), foo: <3>C{op: "pull", tag: "latest", refToTag: "latest", tagExpr: "latestdd", tagInString: "latest"}}
diff --git a/cue/testdata/fulleval/041.txtar b/cue/testdata/fulleval/041.txtar
new file mode 100644
index 0000000..4776cd5
--- /dev/null
+++ b/cue/testdata/fulleval/041.txtar
@@ -0,0 +1,23 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#evalFull
+-- in.cue --
+t: {
+	ok :: *true | bool
+	if ok {
+		x: int
+	}
+}
+s: t & {
+	ok :: false
+}
+-- out/def --
+t: {
+	x:    int
+	ok :: *true | bool
+}
+s: t & {
+	ok :: false
+}
+-- out/legacy-debug --
+<0>{t: <1>{x: int, ok :: true}, s: <2>{ok :: false}}
diff --git a/cue/testdata/fulleval/042_cross-dependent comprehension.txtar b/cue/testdata/fulleval/042_cross-dependent comprehension.txtar
new file mode 100644
index 0000000..8df3a21
--- /dev/null
+++ b/cue/testdata/fulleval/042_cross-dependent comprehension.txtar
@@ -0,0 +1,24 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: cross-dependent comprehension
+#evalFull
+-- in.cue --
+a :: {
+	if b {
+		c: 4
+	}
+	b: bool
+}
+x: (a & {b: true}) & {c: 4}
+y: x
+-- out/def --
+x: _|_ // field "c" not allowed in closed struct
+y: _|_ // field "c" not allowed in closed struct
+a :: {
+	b: bool
+	if b {
+		c: 4
+	}
+}
+-- out/legacy-debug --
+<0>{x: _|_(4:field "c" not allowed in closed struct), y: _|_(4:field "c" not allowed in closed struct), a :: <1>C{b: bool if <2>.b yield <3>C{c: 4}}}
diff --git a/cue/testdata/fulleval/043_optional expanded before lookup.txtar b/cue/testdata/fulleval/043_optional expanded before lookup.txtar
new file mode 100644
index 0000000..b9e21e1
--- /dev/null
+++ b/cue/testdata/fulleval/043_optional expanded before lookup.txtar
@@ -0,0 +1,54 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: optional expanded before lookup
+#evalFull
+-- in.cue --
+test: [ID=_]: {
+	name: ID
+}
+
+test: A: {
+	field1: "1"
+	field2: "2"
+}
+
+B: test.A & {}
+-- out/def --
+test: {
+	{[ID=string]: {
+		name: ID
+	}}
+	A: {
+		name:   "A"
+		field1: "1"
+		field2: "2"
+	}
+}
+B: test.A & {}
+-- out/export --
+test: {
+	A: {
+		name:   "A"
+		field1: "1"
+		field2: "2"
+	}
+}
+B: {
+	name:   "A"
+	field1: "1"
+	field2: "2"
+}
+-- out/yaml --
+test:
+  A:
+    name: A
+    field1: "1"
+    field2: "2"
+B:
+  name: A
+  field1: "1"
+  field2: "2"
+-- out/json --
+{"test":{"A":{"name":"A","field1":"1","field2":"2"}},"B":{"name":"A","field1":"1","field2":"2"}}
+-- out/legacy-debug --
+<0>{test: <1>{[]: <2>(ID: string)-><3>{name: <2>.ID}, A: <4>{name: "A", field1: "1", field2: "2"}}, B: <5>{name: "A", field1: "1", field2: "2"}}
diff --git "a/cue/testdata/fulleval/044_Issue \043178.txtar" "b/cue/testdata/fulleval/044_Issue \043178.txtar"
new file mode 100644
index 0000000..6aa4e0a
--- /dev/null
+++ "b/cue/testdata/fulleval/044_Issue \043178.txtar"
@@ -0,0 +1,26 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: Issue #178
+#evalFull
+-- in.cue --
+import "encoding/csv"
+
+import "encoding/hex"
+
+foo:  csv.Decode(data)
+data: bytes
+
+len: int
+bar: hex.EncodedLen(len)
+-- out/def --
+import (
+	"encoding/csv"
+	"encoding/hex"
+)
+
+foo:  csv.Decode(data)
+data: bytes
+len:  int
+bar:  hex.EncodedLen(len)
+-- out/legacy-debug --
+<0>{foo: <1>.Decode (<2>.data), data: bytes, len: int, bar: <3>.EncodedLen (<2>.len)}
diff --git a/cue/testdata/fulleval/045_comprehension and skipped field.txtar b/cue/testdata/fulleval/045_comprehension and skipped field.txtar
new file mode 100644
index 0000000..2e6c45a
--- /dev/null
+++ b/cue/testdata/fulleval/045_comprehension and skipped field.txtar
@@ -0,0 +1,21 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: comprehension and skipped field
+#evalFull
+-- in.cue --
+
+for key, value in {x: v: 1} {
+	"\(key)": {
+		v:  *{for pod, _ in value.v {}} | {"\(value.v)": 2}
+		_p: 3
+	}
+}
+-- out/def --
+x: {
+	v: {
+		"1": 2
+	}
+	_p: 3
+}
+-- out/legacy-debug --
+<0>{x: <1>{v: <2>{"1": 2}, _p: 3}}
diff --git a/cue/testdata/fulleval/046_non-structural direct cycles.txtar b/cue/testdata/fulleval/046_non-structural direct cycles.txtar
new file mode 100644
index 0000000..6e08cf7
--- /dev/null
+++ b/cue/testdata/fulleval/046_non-structural direct cycles.txtar
@@ -0,0 +1,16 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: non-structural direct cycles
+#evalFull
+-- in.cue --
+c1: {bar: baz: 2} & c1.bar
+c2: {bar:      1} & c2.bar
+-- out/def --
+c1: {
+	bar: {
+		baz: 2
+	}
+} & c1.bar
+c2: _|_ // conflicting values {bar: 1} and 1 (mismatched types struct and int)
+-- out/legacy-debug --
+<0>{c1: <1>{bar: <2>{baz: 2}, baz: 2}, c2: _|_(conflicting values {bar: 1} and 1 (mismatched types struct and int))}
diff --git "a/cue/testdata/fulleval/047_don\047t bind to string labels.txtar" "b/cue/testdata/fulleval/047_don\047t bind to string labels.txtar"
new file mode 100644
index 0000000..617284d
--- /dev/null
+++ "b/cue/testdata/fulleval/047_don\047t bind to string labels.txtar"
@@ -0,0 +1,31 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: don't bind to string labels
+#evalFull
+-- in.cue --
+x: 1
+y: {
+	"x": 2
+	z:   x
+}
+-- out/def --
+x: 1
+y: {
+	x: 2
+	z: 1
+}
+-- out/export --
+x: 1
+y: {
+	x: 2
+	z: 1
+}
+-- out/yaml --
+x: 1
+y:
+  x: 2
+  z: 1
+-- out/json --
+{"x":1,"y":{"x":2,"z":1}}
+-- out/legacy-debug --
+<0>{x: 1, y: <1>{x: 2, z: 1}}
diff --git "a/cue/testdata/fulleval/048_don\047t pass incomplete values to builtins.txtar" "b/cue/testdata/fulleval/048_don\047t pass incomplete values to builtins.txtar"
new file mode 100644
index 0000000..7cd10c1
--- /dev/null
+++ "b/cue/testdata/fulleval/048_don\047t pass incomplete values to builtins.txtar"
@@ -0,0 +1,16 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: don't pass incomplete values to builtins
+#evalFull
+-- in.cue --
+import "encoding/json"
+
+input: string
+foo:   json.Marshal(input)
+-- out/def --
+import "encoding/json"
+
+input: string
+foo:   json.Marshal(input)
+-- out/legacy-debug --
+<0>{input: string, foo: <1>.Marshal (<2>.input)}
diff --git a/cue/testdata/fulleval/049_alias reuse in nested scope.txtar b/cue/testdata/fulleval/049_alias reuse in nested scope.txtar
new file mode 100644
index 0000000..78efaa2
--- /dev/null
+++ b/cue/testdata/fulleval/049_alias reuse in nested scope.txtar
@@ -0,0 +1,66 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: alias reuse in nested scope
+#evalFull
+-- in.cue --
+Foo :: {
+	let X = or([ for k, _ in {} {k}])
+	connection: [X]: X
+}
+A :: {
+	foo: "key"
+	let X = foo
+	a: foo: [X]: X
+}
+B :: {
+	foo: string
+	let X = foo
+	a: foo: [X]: X
+}
+b: B & {foo: "key"}
+-- out/def --
+Foo :: {
+	connection: {
+		[or([ for k, _ in {
+				...
+		} { k } ])]: or([ for k, _ in {
+			...
+		} { k } ])
+	}
+}
+A :: {
+	foo: "key"
+	a: {
+		foo: {
+			["key"]: "key"
+		}
+	}
+}
+B :: {
+	foo: string
+	FOO = foo
+	a: {
+		foo: {
+			[FOO]: FOO
+		}
+	}
+}
+b: B & {
+	foo: "key"
+}
+-- out/export --
+b: {
+	foo: "key"
+	a: {
+		foo: {}
+	}
+}
+-- out/yaml --
+b:
+  foo: key
+  a:
+    foo: {}
+-- out/json --
+{"b":{"foo":"key","a":{"foo":{}}}}
+-- out/legacy-debug --
+<0>{Foo :: <1>C{connection: <2>C{[or ([ <3>for k, _ in <4>{} yield <3>.k ])]: <5>(_: string)->or ([ <3>for k, _ in <4>{} yield <3>.k ]), }}, A :: <6>C{foo: "key", a: <7>C{foo: <8>C{["key"]: <9>(_: string)-><10>.foo, }}}, B :: <11>C{foo: string, a: <12>C{foo: <13>C{[string]: <14>(_: string)-><15>.foo, }}}, b: <16>C{foo: "key", a: <17>C{foo: <18>C{["key"]: <19>(_: string)-><20>.foo, }}}}
diff --git a/cue/testdata/fulleval/050_json Marshaling detects incomplete.txtar b/cue/testdata/fulleval/050_json Marshaling detects incomplete.txtar
new file mode 100644
index 0000000..dff8a179
--- /dev/null
+++ b/cue/testdata/fulleval/050_json Marshaling detects incomplete.txtar
@@ -0,0 +1,24 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: json Marshaling detects incomplete
+#evalFull
+-- in.cue --
+import "encoding/json"
+
+a: json.Marshal({a: string})
+
+foo: {a: 3, b: foo.c}
+b: json.Marshal(foo)
+-- out/def --
+import "encoding/json"
+
+a: json.Marshal({
+	a: string
+})
+foo: {
+	a: 3
+	b: foo.c
+}
+b: json.Marshal(foo)
+-- out/legacy-debug --
+<0>{a: <1>.Marshal (<2>{a: string}), foo: <3>{a: 3, b: <4>.foo.c}, b: <1>.Marshal (<4>.foo)}
diff --git a/cue/testdata/fulleval/051_detectIncompleteYAML.txtar b/cue/testdata/fulleval/051_detectIncompleteYAML.txtar
new file mode 100644
index 0000000..c813ca7
--- /dev/null
+++ b/cue/testdata/fulleval/051_detectIncompleteYAML.txtar
@@ -0,0 +1,68 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: detectIncompleteYAML
+#evalFull
+-- in.cue --
+package foobar
+
+import yaml "encoding/yaml"
+
+Spec :: {
+	_vars: {something: string}
+	data: {
+		foo :: {
+			use: _vars.something
+		}
+		baz:    yaml.Marshal(_vars.something)
+		foobar: yaml.Marshal(foo)
+	}
+}
+Val: Spec & {
+	_vars: something: "var-string"
+}
+-- out/def --
+package foobar
+
+import "encoding/yaml"
+
+Spec :: {
+	_vars: {
+		something: string
+	}
+	data: {
+		foo :: {
+			use: _vars.something
+		}
+		baz:    yaml.Marshal(_vars.something)
+		foobar: yaml.Marshal(foo)
+	}
+}
+Val: Spec & {
+	_vars: {
+		something: "var-string"
+	}
+}
+-- out/export --
+Val: {
+	data: {
+		baz: """
+        var-string
+        
+        """
+		foobar: """
+        use: var-string
+        
+        """
+	}
+}
+-- out/yaml --
+Val:
+  data:
+    baz: |
+      var-string
+    foobar: |
+      use: var-string
+-- out/json --
+{"Val":{"data":{"baz":"var-string\n","foobar":"use: var-string\n"}}}
+-- out/legacy-debug --
+<0>{Spec :: <1>C{_vars: <2>C{something: string}, data: <3>C{foo :: <4>C{use: string}, baz: <5>.Marshal (<6>._vars.something), foobar: <5>.Marshal (<7>.foo)}}, Val: <8>C{_vars: <9>C{something: "var-string"}, data: <10>C{foo :: <11>C{use: "var-string"}, baz: "var-string\n", foobar: "use: var-string\n"}}}
diff --git a/cue/testdata/fulleval/052_detectIncompleteJSON.txtar b/cue/testdata/fulleval/052_detectIncompleteJSON.txtar
new file mode 100644
index 0000000..0a45cf2
--- /dev/null
+++ b/cue/testdata/fulleval/052_detectIncompleteJSON.txtar
@@ -0,0 +1,60 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: detectIncompleteJSON
+#evalFull
+-- in.cue --
+package foobar
+
+import "encoding/json"
+
+Spec :: {
+	_vars: {something: string}
+	data: {
+		foo :: {
+			use: _vars.something
+		}
+		baz:    json.Marshal(_vars.something)
+		foobar: json.Marshal(foo)
+	}
+}
+Val: Spec & {
+	_vars: something: "var-string"
+}
+-- out/def --
+package foobar
+
+import "encoding/json"
+
+Spec :: {
+	_vars: {
+		something: string
+	}
+	data: {
+		foo :: {
+			use: _vars.something
+		}
+		baz:    json.Marshal(_vars.something)
+		foobar: json.Marshal(foo)
+	}
+}
+Val: Spec & {
+	_vars: {
+		something: "var-string"
+	}
+}
+-- out/export --
+Val: {
+	data: {
+		baz:    "\"var-string\""
+		foobar: "{\"use\":\"var-string\"}"
+	}
+}
+-- out/yaml --
+Val:
+  data:
+    baz: '"var-string"'
+    foobar: '{"use":"var-string"}'
+-- out/json --
+{"Val":{"data":{"baz":"\"var-string\"","foobar":"{\"use\":\"var-string\"}"}}}
+-- out/legacy-debug --
+<0>{Spec :: <1>C{_vars: <2>C{something: string}, data: <3>C{foo :: <4>C{use: string}, baz: <5>.Marshal (<6>._vars.something), foobar: <5>.Marshal (<7>.foo)}}, Val: <8>C{_vars: <9>C{something: "var-string"}, data: <10>C{foo :: <11>C{use: "var-string"}, baz: "\"var-string\"", foobar: "{\"use\":\"var-string\"}"}}}
diff --git a/cue/testdata/fulleval/053_issue312.txtar b/cue/testdata/fulleval/053_issue312.txtar
new file mode 100644
index 0000000..161329c
--- /dev/null
+++ b/cue/testdata/fulleval/053_issue312.txtar
@@ -0,0 +1,22 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: issue312
+#evalFull
+-- in.cue --
+
+for x in [1] {
+	*close({}) | {[_]: null}
+}
+-- out/def --
+
+for x in [1] *close({}) | {
+	[string]: null
+}
+-- out/export --
+
+-- out/yaml --
+{}
+-- out/json --
+{}
+-- out/legacy-debug --
+<0>{ <1>for _, x in [1] yield <2>{}, (*close (<3>{}) | <4>{[]: <5>(_: string)->null, })}
diff --git a/cue/testdata/fulleval/054_issue312.txtar b/cue/testdata/fulleval/054_issue312.txtar
new file mode 100644
index 0000000..9d98a87
--- /dev/null
+++ b/cue/testdata/fulleval/054_issue312.txtar
@@ -0,0 +1,22 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: issue312
+#evalFull
+-- in.cue --
+y: *1 | {a: 2}
+for x in [1] {y}
+-- out/def --
+y: *1 | {
+	a: 2
+}
+a: 2
+-- out/export --
+y: 1
+a: 2
+-- out/yaml --
+y: 1
+a: 2
+-- out/json --
+{"y":1,"a":2}
+-- out/legacy-debug --
+<0>{y: 1, a: 2}
diff --git a/cue/testdata/fulleval/055_issue318.txtar b/cue/testdata/fulleval/055_issue318.txtar
new file mode 100644
index 0000000..424b9fb
--- /dev/null
+++ b/cue/testdata/fulleval/055_issue318.txtar
@@ -0,0 +1,30 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: issue318
+#evalFull
+-- in.cue --
+T :: {
+	arg: x: string
+	out1: "\(arg.x) \(arg.y)"
+	out2: "\(arg.y)"
+	vx:   arg.x
+	vy:   arg.y
+}
+-- out/def --
+T :: {
+	arg: {
+		x: string
+	}
+	out1: _|_ // undefined field "y"
+	out2: _|_ // undefined field "y"
+	vx:   arg.x
+	vy:   _|_ // undefined field "y"
+}
+-- out/export --
+
+-- out/yaml --
+{}
+-- out/json --
+{}
+-- out/legacy-debug --
+<0>{T :: <1>C{arg: <2>C{x: string}, out1: _|_(<3>.arg.y:undefined field "y"), out2: _|_(<3>.arg.y:undefined field "y"), vx: string, vy: _|_(<3>.arg.y:undefined field "y")}}
diff --git a/cue/testdata/fulleval/056_issue314.txtar b/cue/testdata/fulleval/056_issue314.txtar
new file mode 100644
index 0000000..26521a3
--- /dev/null
+++ b/cue/testdata/fulleval/056_issue314.txtar
@@ -0,0 +1,77 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: issue314
+#evalFull
+-- in.cue --
+import (
+	"text/template"
+	"encoding/yaml"
+	"encoding/json"
+)
+
+x: {
+	s: "myname"
+	T
+}
+
+T :: {
+	s:   string
+	out: template.Execute("{{.s}}", {
+		"s": s
+	})
+}
+
+V :: {
+	s:   string
+	out: json.Marshal({"s": s})
+}
+
+U :: {
+	s:   string
+	out: yaml.Marshal({"s": s})
+}
+-- out/def --
+import (
+	"encoding/json"
+	"encoding/yaml"
+	"text/template"
+)
+
+T :: {
+	s: string
+	S = s
+	out: template.Execute("{{.s}}", {
+		s: S
+	})
+}
+x: {
+	s: "myname"
+	T
+}
+V :: {
+	s: string
+	S658221 = s
+	out: json.Marshal({
+		s: S658221
+	})
+}
+U :: {
+	s: string
+	S629a0f = s
+	out: yaml.Marshal({
+		s: S629a0f
+	})
+}
+-- out/export --
+x: {
+	s:   "myname"
+	out: "myname"
+}
+-- out/yaml --
+x:
+  s: myname
+  out: myname
+-- out/json --
+{"x":{"s":"myname","out":"myname"}}
+-- out/legacy-debug --
+<0>{T :: <1>C{s: string, out: <2>.Execute ("{{.s}}",<3>C{s: <4>.s})}, x: <5>C{s: "myname", out: "myname"}, V :: <6>C{s: string, out: <7>.Marshal (<8>C{s: <9>.s})}, U :: <10>C{s: string, out: <11>.Marshal (<12>C{s: <13>.s})}}
diff --git a/cue/testdata/gen.go b/cue/testdata/gen.go
new file mode 100644
index 0000000..906b1aa
--- /dev/null
+++ b/cue/testdata/gen.go
@@ -0,0 +1,310 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"bytes"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/constant"
+	"go/format"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+	"golang.org/x/tools/txtar"
+
+	"cuelang.org/go/cue"
+	cueast "cuelang.org/go/cue/ast"
+	cueformat "cuelang.org/go/cue/format"
+	"cuelang.org/go/internal"
+	"cuelang.org/go/pkg/encoding/yaml"
+)
+
+func main() {
+	flag.Parse()
+	log.SetFlags(log.Lshortfile)
+
+	cfg := &packages.Config{
+		Mode: packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo,
+
+		Tests: true,
+	}
+	a, err := packages.Load(cfg, "..")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	for _, p := range a {
+		e := extractor{p: p}
+		e.extractFromPackage()
+	}
+}
+
+type extractor struct {
+	p *packages.Package
+
+	dir    string
+	name   string
+	count  int
+	a      *txtar.Archive
+	header *bytes.Buffer
+
+	tags []string
+}
+
+func (e *extractor) fatalf(format string, args ...interface{}) {
+	prefix := fmt.Sprintf("%s/%d[%s]: ", e.dir, e.count, e.name)
+	log.Fatalf(prefix+format, args...)
+}
+
+func (e *extractor) warnf(format string, args ...interface{}) {
+	prefix := fmt.Sprintf("%s/%d[%s]: ", e.dir, e.count, e.name)
+	log.Printf(prefix+format, args...)
+}
+
+func (e *extractor) extractFromPackage() {
+	for _, file := range e.p.Syntax {
+		for _, d := range file.Decls {
+			e.processTestFunc(d)
+		}
+	}
+}
+
+func (e *extractor) processTestFunc(d ast.Decl) {
+	p := e.p
+	f, ok := d.(*ast.FuncDecl)
+	if !ok {
+		return
+	}
+
+	if !strings.HasPrefix(f.Name.Name, "Test") {
+		return
+	}
+	e.dir = strings.ToLower(f.Name.Name[len("Test"):])
+	e.count = 0
+	e.tags = nil
+	if e.dir == "x" { // TestX
+		return
+	}
+
+	if len(f.Type.Params.List) != 1 {
+		return
+	}
+
+	if p.TypesInfo.TypeOf(f.Type.Params.List[0].Type).String() != "*testing.T" {
+		return
+	}
+	e.extractFromTestFunc(f)
+}
+
+func (e *extractor) isConstant(x ast.Expr) bool {
+	return constant.Val(e.p.TypesInfo.Types[x].Value) != nil
+}
+
+func (e *extractor) stringConst(x ast.Expr) string {
+	v := e.p.TypesInfo.Types[x].Value
+	if v.Kind() != constant.String {
+		return v.String()
+	}
+	return constant.StringVal(v)
+}
+
+func (e *extractor) boolConst(x ast.Expr) bool {
+	v := e.p.TypesInfo.Types[x].Value
+	return constant.BoolVal(v)
+}
+
+func (e *extractor) exprString(x ast.Expr) string {
+	w := &bytes.Buffer{}
+	_ = format.Node(w, e.p.Fset, x)
+	return w.String()
+}
+
+func (e *extractor) extractFromTestFunc(f *ast.FuncDecl) {
+	defer func() {
+		if err := recover(); err != nil {
+			e.warnf("PANIC: %v", err)
+			panic(err)
+		}
+	}()
+	// Extract meta data.
+	for _, stmt := range f.Body.List {
+		es, ok := stmt.(*ast.ExprStmt)
+		if !ok {
+			continue
+		}
+		if call, ok := es.X.(*ast.CallExpr); ok {
+			if e.exprString(call.Fun) != "rewriteHelper" {
+				continue
+			}
+			e.tags = append(e.tags, e.exprString(call.Args[2]))
+		}
+	}
+
+	// Extract test data.
+	for _, stmt := range f.Body.List {
+		ast.Inspect(stmt, func(n ast.Node) bool {
+			switch x := n.(type) {
+			case *ast.CompositeLit:
+				t := e.p.TypesInfo.TypeOf(x.Type)
+
+				switch t.String() {
+				case "[]cuelang.org/go/cue.testCase",
+					"[]cuelang.org/go/cue.exportTest":
+					// TODO: "[]cuelang.org/go/cue.subsumeTest",
+				default:
+					return false
+				}
+
+				for _, elt := range x.Elts {
+					if kv, ok := elt.(*ast.KeyValueExpr); ok {
+						elt = kv.Value
+					}
+					e.extractTest(elt.(*ast.CompositeLit))
+					e.count++
+				}
+
+				return false
+			}
+			return true
+		})
+	}
+}
+
+func (e *extractor) extractTest(x *ast.CompositeLit) {
+	e.name = ""
+	e.header = &bytes.Buffer{}
+	e.a = &txtar.Archive{}
+
+	e.header.WriteString(`# DO NOT EDIT; generated by go run testdata/gen.go
+#
+`)
+
+	for _, elmt := range x.Elts {
+		f, ok := elmt.(*ast.KeyValueExpr)
+		if !ok {
+			e.fatalf("Invalid slice element: %T", elmt)
+			continue
+		}
+
+		switch key := e.exprString(f.Key); key {
+		case "name", "desc":
+			e.name = e.stringConst(f.Value)
+			fmt.Fprintf(e.header, "#name: %v\n", e.stringConst(f.Value))
+
+		case "in":
+			src := []byte(e.stringConst(f.Value))
+			src, err := cueformat.Source(src)
+			if err != nil {
+				fmt.Fprintln(e.header, "#skip")
+				e.warnf("Skipped: %v", err)
+				continue
+			}
+			e.a.Files = append(e.a.Files, txtar.File{
+				Name: "in.cue",
+				Data: src,
+			})
+
+			e.populate(src)
+
+		case "out":
+			if !e.isConstant(f.Value) {
+				e.warnf("Could not determine value for 'out' field")
+				continue
+			}
+			e.a.Files = append(e.a.Files, txtar.File{
+				Name: "out/legacy-debug",
+				Data: []byte(e.stringConst(f.Value)),
+			})
+		default:
+			fmt.Fprintf(e.header, "%s: %v\n", key, e.exprString(f.Value))
+		}
+	}
+
+	for _, t := range e.tags {
+		fmt.Fprintf(e.header, "#%s\n", t)
+	}
+
+	e.a.Comment = e.header.Bytes()
+
+	_ = os.Mkdir(e.dir, 0755)
+
+	name := fmt.Sprintf("%03d", e.count)
+	if e.name != "" {
+		name += "_" + e.name
+	}
+	// name = strings.ReplaceAll(name, " ", "_")
+	filename := filepath.Join(e.dir, name+".txtar")
+	err := ioutil.WriteFile(filename, txtar.Format(e.a), 0644)
+	if err != nil {
+		e.fatalf("Could not write file: %v", err)
+	}
+}
+
+// populate sets the golden tests based on the old compiler, evaluator,
+// and exporter.
+func (e *extractor) populate(src []byte) {
+	r := cue.Runtime{}
+	inst, err := r.Compile("in.cue", src)
+	if err != nil {
+		e.fatalf("Failed to parse: %v", err)
+	}
+
+	v := inst.Value()
+
+	e.addFile(e.a, "out/def", v.Syntax(
+		cue.Docs(true),
+		cue.Attributes(true),
+		cue.Optional(true),
+		cue.Definitions(true)))
+
+	if v.Validate(cue.Concrete(true)) == nil {
+		e.addFile(e.a, "out/export", v.Syntax(
+			cue.Concrete(true),
+			cue.Final(),
+			cue.Docs(true),
+			cue.Attributes(true)))
+
+		s, err := yaml.Marshal(v)
+		if err != nil {
+			fmt.Fprintln(e.header, "#bug: true")
+			e.warnf("Could not encode as YAML: %v", err)
+		}
+		e.a.Files = append(e.a.Files,
+			txtar.File{Name: "out/yaml", Data: []byte(s)})
+
+		b, err := json.Marshal(v)
+		if err != nil {
+			fmt.Fprintln(e.header, "#bug: true")
+			e.warnf("Could not encode as JSON: %v", err)
+		}
+		e.a.Files = append(e.a.Files,
+			txtar.File{Name: "out/json", Data: b})
+	}
+}
+
+func (e *extractor) addFile(a *txtar.Archive, name string, n cueast.Node) {
+	b, err := cueformat.Node(internal.ToFile(n))
+	if err != nil {
+		e.fatalf("Failed to format %s: %v\n", name, err)
+	}
+	a.Files = append(a.Files, txtar.File{Name: name, Data: b})
+}
diff --git a/cue/testdata/readme.md b/cue/testdata/readme.md
new file mode 100644
index 0000000..c8ca873
--- /dev/null
+++ b/cue/testdata/readme.md
@@ -0,0 +1,31 @@
+## CUE Test Suite
+
+This directory contains a test suite for testing the CUE language. This is only
+intended to test language evaluation and exporting. Eventually it will also
+contains tests for parsing and formatting. It is not intended to cover
+testing of the API itself.
+
+WORK IN PROGRESS
+
+The tests are currently converted from various internal Go tests and the
+grouping reflect properties of the current implementation. Once the transition
+to the new implementation is completed, tests should be reordered along more
+logical lines: such as literals, expressions, references, cycles, etc.
+
+FORESEEN STRUCTURE
+
+The txtar format allows a collection of files to be defined. Any .cue file
+is used as an input. The out/* files, which should not have an extension,
+define outputs for various tests. A test definition is active for a certain test
+if it contains output for this test.
+
+The comments section of the txtar file may contain additional control inputs for
+a test. Each line that starts with a `#` immediately followed by a letter or
+digit is specially interpreted. These can be boolean tags (`#foo`) or a
+key-value pair (`#key: value`), where the value can be a free-form string.
+A line starting with `#` followed by a space is interpreted as a comment.
+
+Lines not starting with a `#` are for interpretation by the testscript package.
+
+This organization allows the same test sets to be used for the testing of
+tooling as well as internal libraries.
\ No newline at end of file
diff --git a/cue/testdata/resolve/000_convert _ to top.txtar b/cue/testdata/resolve/000_convert _ to top.txtar
new file mode 100644
index 0000000..225b213
--- /dev/null
+++ b/cue/testdata/resolve/000_convert _ to top.txtar
@@ -0,0 +1,18 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: convert _ to top
+#evalPartial
+-- in.cue --
+a: {[_]: _}
+-- out/def --
+a: {
+	...
+}
+-- out/export --
+a: {}
+-- out/yaml --
+a: {}
+-- out/json --
+{"a":{}}
+-- out/legacy-debug --
+<0>{a: <1>{...}}
diff --git a/cue/testdata/resolve/001.txtar b/cue/testdata/resolve/001.txtar
new file mode 100644
index 0000000..e29c98d
--- /dev/null
+++ b/cue/testdata/resolve/001.txtar
@@ -0,0 +1,47 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#evalPartial
+-- in.cue --
+a: b.c.d
+b: c: {d: 3}
+c: {c: d.d}
+d: {d: 2}
+-- out/def --
+a: 3
+b: {
+	c: {
+		d: 3
+	}
+}
+c: {
+	c: 2
+}
+d: {
+	d: 2
+}
+-- out/export --
+a: 3
+b: {
+	c: {
+		d: 3
+	}
+}
+c: {
+	c: 2
+}
+d: {
+	d: 2
+}
+-- out/yaml --
+a: 3
+b:
+  c:
+    d: 3
+c:
+  c: 2
+d:
+  d: 2
+-- out/json --
+{"a":3,"b":{"c":{"d":3}},"c":{"c":2},"d":{"d":2}}
+-- out/legacy-debug --
+<0>{a: 3, b: <1>{c: <2>{d: 3}}, c: <3>{c: 2}, d: <4>{d: 2}}
diff --git a/cue/testdata/resolve/002.txtar b/cue/testdata/resolve/002.txtar
new file mode 100644
index 0000000..6732627
--- /dev/null
+++ b/cue/testdata/resolve/002.txtar
@@ -0,0 +1,6 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#skip
+#evalPartial
+-- out/legacy-debug --
+<0>{x: 3, "foo-bar": 3}
diff --git a/cue/testdata/resolve/003_resolution of quoted identifiers.txtar b/cue/testdata/resolve/003_resolution of quoted identifiers.txtar
new file mode 100644
index 0000000..d65b967
--- /dev/null
+++ b/cue/testdata/resolve/003_resolution of quoted identifiers.txtar
@@ -0,0 +1,7 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: resolution of quoted identifiers
+#skip
+#evalPartial
+-- out/legacy-debug --
+<0>{"foo-bar": 2, baz: 2, a: <1>{qux: 3, "qux-quux": 3, qaz: 3}}
diff --git a/cue/testdata/resolve/004.txtar b/cue/testdata/resolve/004.txtar
new file mode 100644
index 0000000..fb78102
--- /dev/null
+++ b/cue/testdata/resolve/004.txtar
@@ -0,0 +1,29 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#evalPartial
+-- in.cue --
+a: _
+b: a
+a: {d: 1, d: _}
+b: _
+-- out/def --
+a: {
+	d: 1
+}
+b: a
+-- out/export --
+a: {
+	d: 1
+}
+b: {
+	d: 1
+}
+-- out/yaml --
+a:
+  d: 1
+b:
+  d: 1
+-- out/json --
+{"a":{"d":1},"b":{"d":1}}
+-- out/legacy-debug --
+<0>{a: <1>{d: 1}, b: <2>{d: 1}}
diff --git a/cue/testdata/resolve/005_JSON.txtar b/cue/testdata/resolve/005_JSON.txtar
new file mode 100644
index 0000000..96256de
--- /dev/null
+++ b/cue/testdata/resolve/005_JSON.txtar
@@ -0,0 +1,36 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: JSON
+#evalPartial
+-- in.cue --
+a="a": 3
+b:     a
+o: {"a\nb": 2} // TODO: use $ for root?
+c: o["a\nb"]
+-- out/def --
+a: 3
+b: 3
+o: {
+	"a\nb": 2
+}
+c: 2
+-- out/export --
+a: 3
+b: 3
+o: {
+	"a\nb": 2
+}
+c: 2
+-- out/yaml --
+a: 3
+b: 3
+o:
+  ? |-
+    a
+    b
+  : 2
+c: 2
+-- out/json --
+{"a":3,"b":3,"o":{"a\nb":2},"c":2}
+-- out/legacy-debug --
+<0>{a: 3, b: 3, o: <1>{"a\nb": 2}, c: 2}
diff --git a/cue/testdata/resolve/006_arithmetic.txtar b/cue/testdata/resolve/006_arithmetic.txtar
new file mode 100644
index 0000000..8578e90
--- /dev/null
+++ b/cue/testdata/resolve/006_arithmetic.txtar
@@ -0,0 +1,20 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: arithmetic
+#evalPartial
+-- in.cue --
+v1: 1.0T / 2.0
+v2: 2.0 == 2
+n1: 1
+v5: 2.0 / n1
+v6: 1.0 / 1.0
+e2: int & 4.0/2.0
+-- out/def --
+v1: 5.0000000000e+11
+v2: true
+n1: 1
+v5: 2.0
+v6: 1.
+e2: _|_ // conflicting values int and (4.0 / 2.0) (mismatched types int and float)
+-- out/legacy-debug --
+<0>{v1: 5.0000000000e+11, v2: true, n1: 1, v5: 2.0, v6: 1., e2: _|_((int & (4.0 / 2.0)):conflicting values int and (4.0 / 2.0) (mismatched types int and float))}
diff --git a/cue/testdata/resolve/007_inequality.txtar b/cue/testdata/resolve/007_inequality.txtar
new file mode 100644
index 0000000..4df5fe2
--- /dev/null
+++ b/cue/testdata/resolve/007_inequality.txtar
@@ -0,0 +1,36 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: inequality
+#evalPartial
+-- in.cue --
+a: 1 != 2
+b: 1 != null
+c: true == null
+d: null != {}
+e: null == []
+f: 0 == 0.0 // types are unified first TODO: make this consistent
+-- out/def --
+a: true
+b: true
+c: false
+d: true
+e: false
+f: true
+-- out/export --
+a: true
+b: true
+c: false
+d: true
+e: false
+f: true
+-- out/yaml --
+a: true
+b: true
+c: false
+d: true
+e: false
+f: true
+-- out/json --
+{"a":true,"b":true,"c":false,"d":true,"e":false,"f":true}
+-- out/legacy-debug --
+<0>{a: true, b: true, c: false, d: true, e: false, f: true}
diff --git a/cue/testdata/resolve/008_attributes.txtar b/cue/testdata/resolve/008_attributes.txtar
new file mode 100644
index 0000000..3b4bd00
--- /dev/null
+++ b/cue/testdata/resolve/008_attributes.txtar
@@ -0,0 +1,21 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: attributes
+#evalPartial
+-- in.cue --
+a: {foo: 1 @foo() @baz(1)}
+b: {foo: 1 @bar() @foo()}
+c: a & b
+
+e: a & {foo: 1 @foo(other)}
+-- out/def --
+a: {
+	foo: 1 @baz(1) @foo()
+}
+b: {
+	foo: 1 @bar() @foo()
+}
+c: a & b
+e: _|_ // conflicting attributes for key "foo"
+-- out/legacy-debug --
+<0>{a: <1>{foo: 1 @baz(1) @foo()}, b: <2>{foo: 1 @bar() @foo()}, c: <3>{foo: 1 @bar() @baz(1) @foo()}, e: _|_((<4>.a & <5>{foo: 1 @foo(other)}):conflicting attributes for key "foo")}
diff --git a/cue/testdata/resolve/009_optional field unification.txtar b/cue/testdata/resolve/009_optional field unification.txtar
new file mode 100644
index 0000000..4e8b4db
--- /dev/null
+++ b/cue/testdata/resolve/009_optional field unification.txtar
@@ -0,0 +1,48 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: optional field unification
+#evalPartial
+-- in.cue --
+a: {foo?: string}
+b: {foo: "foo"}
+c: a & b
+d: a & {"foo"?: "bar"}
+
+g1:       1
+"g\(1)"?: 1
+"g\(2)"?: 2
+-- out/def --
+a: {
+	foo?: string
+}
+b: {
+	foo: "foo"
+}
+c: a & b
+d: a & {
+	foo?: "bar"
+}
+g1:  1
+g2?: 2
+-- out/export --
+a: {}
+b: {
+	foo: "foo"
+}
+c: {
+	foo: "foo"
+}
+d: {}
+g1: 1
+-- out/yaml --
+a: {}
+b:
+  foo: foo
+c:
+  foo: foo
+d: {}
+g1: 1
+-- out/json --
+{"a":{},"b":{"foo":"foo"},"c":{"foo":"foo"},"d":{},"g1":1}
+-- out/legacy-debug --
+<0>{a: <1>{foo?: string}, b: <2>{foo: "foo"}, c: <3>{foo: "foo"}, d: <4>{foo?: "bar"}, g1: 1, g2?: 2}
diff --git a/cue/testdata/resolve/010_optional field resolves to incomplete.txtar b/cue/testdata/resolve/010_optional field resolves to incomplete.txtar
new file mode 100644
index 0000000..1067bc4
--- /dev/null
+++ b/cue/testdata/resolve/010_optional field resolves to incomplete.txtar
@@ -0,0 +1,18 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: optional field resolves to incomplete
+#evalPartial
+-- in.cue --
+r: {
+	a?: 3
+	b:  a
+	c:  r["a"]
+}
+-- out/def --
+r: {
+	a?: 3
+	b:  a
+	c:  r["a"]
+}
+-- out/legacy-debug --
+<0>{r: <1>{a?: 3, b: <2>.a, c: <3>.r["a"]}}
diff --git a/cue/testdata/resolve/011_bounds.txtar b/cue/testdata/resolve/011_bounds.txtar
new file mode 100644
index 0000000..ef8b147
--- /dev/null
+++ b/cue/testdata/resolve/011_bounds.txtar
@@ -0,0 +1,96 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: bounds
+#evalPartial
+-- in.cue --
+i1: >1 & 5
+i2: (>=0 & <=10) & 5
+i3: !=null & []
+i4: !=2 & !=4
+
+s1: >=0 & <=10 & !=1  // no simplification
+s2: >=0 & <=10 & !=11 // >=0 & <=10
+s3: >5 & !=5          // >5
+s4: <10 & !=10        // <10
+s5: !=2 & !=2
+
+// TODO: could change inequality
+s6: !=2 & >=2
+s7: >=2 & !=2
+
+s8: !=5 & >5
+
+s10: >=0 & <=10 & <12 & >1 // >1  & <=10
+s11: >0 & >=0 & <=12 & <12 // >0  & <12
+
+s20: >=10 & <=10 // 10
+
+s22:  >5 & <=6         // no simplification
+s22a: >5 & (<=6 & int) // 6
+s22b: (int & >5) & <=6 // 6
+s22c: >=5 & (<6 & int) // 5
+s22d: (int & >=5) & <6 // 5
+s22e: (>=5 & <6) & int // 5
+s22f: int & (>=5 & <6) // 5
+
+s23:  >0 & <2         // no simplification
+s23a: (>0 & <2) & int // int & 1
+s23b: int & (>0 & <2) // int & 1
+s23c: (int & >0) & <2 // int & 1
+s23d: >0 & (int & <2) // int & 1
+s23e: >0.0 & <2.0     // no simplification
+
+s30: >0 & int
+
+e1: null & !=null
+e2: !=null & null
+e3: >1 & 1
+e4: <0 & 0
+e5: >1 & <0
+e6: >11 & <11
+e7: >=11 & <11
+e8: >11 & <=11
+e9: >"a" & <1
+-- out/def --
+i1: 5
+i2: 5
+i3: []
+i4: !=2 & !=4
+s1: >=0 & <=10 & !=1
+s2: >=0 & <=10
+s3: >5
+s4: <10
+s5: !=2
+
+// TODO: could change inequality
+s6:   !=2
+s7:   !=2
+s8:   >5
+s10:  >1 & <=10
+s11:  >0 & <12
+s20:  10
+s22:  >5 & <=6
+s22a: 6
+s22b: 6
+s22c: 5
+s22d: 5
+s22e: 5
+s22f: 5
+s23:  >0 & <2
+s23a: 1
+s23b: 1
+s23c: 1
+s23d: 1
+s23e: >0.0 & <2.0
+s30:  >0
+e1:   _|_ // invalid value null (excluded by !=null)
+e2:   _|_ // invalid value null (excluded by !=null)
+e3:   _|_ // invalid value 1 (out of bound >1)
+e4:   _|_ // invalid value 0 (out of bound <0)
+e5:   _|_ // conflicting bounds >1 and <0
+e6:   _|_ // conflicting bounds >11 and <11
+e7:   _|_ // conflicting bounds >=11 and <11
+e8:   _|_ // conflicting bounds >11 and <=11
+e9:   _|_ // conflicting values >"a" and <1 (mismatched types string and number)
+-- out/legacy-debug --
+<0>{i1: 5, i2: 5, i3: [], i4: (!=2 & !=4), s1: (>=0 & <=10 & !=1), s2: (>=0 & <=10), s3: >5, s4: <10, s5: !=2, s6: (!=2 & >=2), s7: (>=2 & !=2), s8: >5, s10: (<=10 & >1), s11: (>0 & <12), s20: 10, s22: (>5 & <=6), s22a: 6, s22b: 6, s22c: 5, s22d: 5, s22e: 5, s22f: 5, s23: (>0 & <2), s23a: 1, s23b: 1, s23c: 1, s23d: 1, s23e: (>0.0 & <2.0), s30: int & >0, e1: _|_((!=null & null):invalid value null (excluded by !=null)), e2: _|_((!=null & null):invalid value null (excluded by !=null)), e3: _|_((>1 & 1):invalid value 1 (out of bound >1)), e4: _|_((<0 & 0):invalid value 0 (out of bound <0)), e5: _|_(conflicting bounds >1 and <0), e6: _|_(conflicting bounds >11 and <11), e7: _|_(conflicting bounds >=11 and <11), e8: _|_(conflicting bounds >11 and <=11), e9: _|_((>"a" & <1):conflicting values >"a" and <1 (mismatched types string and number))}
diff --git a/cue/testdata/resolve/012_bound conversions.txtar b/cue/testdata/resolve/012_bound conversions.txtar
new file mode 100644
index 0000000..9579755
--- /dev/null
+++ b/cue/testdata/resolve/012_bound conversions.txtar
@@ -0,0 +1,33 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: bound conversions
+#evalPartial
+-- in.cue --
+r0: int & >0.1 & <=1.9
+r1: int & >0.1 & <1.9
+r2: int & >=0.1 & <1.9
+r3: int & >=-1.9 & <=-0.1
+r4: int & >-1.9 & <=-0.1
+
+r5: >=1.1 & <=1.1
+r6: r5 & 1.1
+
+c1: (1.2 & >1.3) & <2
+c2: 1.2 & (>1.3 & <2)
+
+c3: 1.2 & (>=1 & <2)
+c4: 1.2 & (>=1 & <2 & int)
+-- out/def --
+r0: 1
+r1: 1
+r2: 1
+r3: -1
+r4: -1
+r5: 1.1
+r6: 1.1
+c1: _|_ // invalid value 1.2 (out of bound >1.3)
+c2: _|_ // invalid value 1.2 (out of bound >1.3)
+c3: 1.2
+c4: _|_ // conflicting values 1.2 and ((>=1 & <2) & int) (mismatched types float and int)
+-- out/legacy-debug --
+<0>{r0: 1, r1: 1, r2: 1, r3: -1, r4: -1, r5: 1.1, r6: 1.1, c1: _|_((>1.3 & 1.2):invalid value 1.2 (out of bound >1.3)), c2: _|_((>1.3 & 1.2):invalid value 1.2 (out of bound >1.3)), c3: 1.2, c4: _|_((1.2 & ((>=1 & <2) & int)):conflicting values 1.2 and ((>=1 & <2) & int) (mismatched types float and int))}
diff --git a/cue/testdata/resolve/013_custom validators.txtar b/cue/testdata/resolve/013_custom validators.txtar
new file mode 100644
index 0000000..25b566a
--- /dev/null
+++ b/cue/testdata/resolve/013_custom validators.txtar
@@ -0,0 +1,21 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: custom validators
+#evalPartial
+-- in.cue --
+import "strings"
+
+a: strings.ContainsAny("ab")
+a: "after"
+
+b: strings.ContainsAny("c")
+b: "dog"
+
+c: strings.ContainsAny("d") & strings.ContainsAny("g")
+c: "dog"
+-- out/def --
+a: "after"
+b: _|_ // invalid value "dog" (does not satisfy strings.ContainsAny("c"))
+c: "dog"
+-- out/legacy-debug --
+<0>{a: "after", b: _|_(strings.ContainsAny ("c"):invalid value "dog" (does not satisfy strings.ContainsAny("c"))), c: "dog"}
diff --git a/cue/testdata/resolve/014_null coalescing.txtar b/cue/testdata/resolve/014_null coalescing.txtar
new file mode 100644
index 0000000..97f90ec
--- /dev/null
+++ b/cue/testdata/resolve/014_null coalescing.txtar
@@ -0,0 +1,24 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: null coalescing
+#evalPartial
+-- in.cue --
+a: null
+b: a.x | "b"
+c: a["x"] | "c"
+-- out/def --
+a: null
+b: "b"
+c: "c"
+-- out/export --
+a: null
+b: "b"
+c: "c"
+-- out/yaml --
+a: null
+b: b
+c: c
+-- out/json --
+{"a":null,"b":"b","c":"c"}
+-- out/legacy-debug --
+<0>{a: null, b: "b", c: "c"}
diff --git a/cue/testdata/resolve/015_reference across tuples and back.txtar b/cue/testdata/resolve/015_reference across tuples and back.txtar
new file mode 100644
index 0000000..f31191b
--- /dev/null
+++ b/cue/testdata/resolve/015_reference across tuples and back.txtar
@@ -0,0 +1,36 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: reference across tuples and back
+#evalPartial
+-- in.cue --
+a: {c: b.e, d: b.f}
+b: {e: 3, f: a.c}
+-- out/def --
+a: {
+	c: 3
+	d: 3
+}
+b: {
+	e: 3
+	f: 3
+}
+-- out/export --
+a: {
+	c: 3
+	d: 3
+}
+b: {
+	e: 3
+	f: 3
+}
+-- out/yaml --
+a:
+  c: 3
+  d: 3
+b:
+  e: 3
+  f: 3
+-- out/json --
+{"a":{"c":3,"d":3},"b":{"e":3,"f":3}}
+-- out/legacy-debug --
+<0>{a: <1>{c: 3, d: 3}, b: <2>{e: 3, f: 3}}
diff --git a/cue/testdata/resolve/016_index.txtar b/cue/testdata/resolve/016_index.txtar
new file mode 100644
index 0000000..f5d6b0f
--- /dev/null
+++ b/cue/testdata/resolve/016_index.txtar
@@ -0,0 +1,40 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: index
+#evalPartial
+-- in.cue --
+a: [2][0]
+b: {foo:       "bar"}["foo"]
+c: (*l | {"3": 3})["3"]
+d: (*[] | [1])[0]
+l: []
+e1: [2][""]
+e2: 2[2]
+e3: [][true]
+e4: [1, 2, 3][3]
+e5: [1, 2, 3][-1]
+e6: (*[] | {})[1]
+def: {
+	a:   1
+	b :: 3
+}
+e7: def["b"]
+-- out/def --
+a: 2
+b: "bar"
+c: _|_ // invalid list index "3" (type string)
+l: []
+d:  _|_ // index 0 out of bounds
+e1: _|_ // invalid list index "" (type string)
+e2: _|_ // invalid operation: 2[2] (type int does not support indexing)
+e3: _|_ // invalid list index true (type bool)
+e4: _|_ // index 3 out of bounds
+e5: _|_ // invalid list index -1 (index must be non-negative)
+e6: _|_ // index 1 out of bounds
+def: {
+	a:   1
+	b :: 3
+}
+e7: _|_ // field "b" is a definition
+-- out/legacy-debug --
+<0>{a: 2, b: "bar", c: _|_("3":invalid list index "3" (type string)), l: [], d: _|_([]:index 0 out of bounds), e1: _|_("":invalid list index "" (type string)), e2: _|_(2:invalid operation: 2[2] (type int does not support indexing)), e3: _|_(true:invalid list index true (type bool)), e4: _|_([1,2,3]:index 3 out of bounds), e5: _|_(-1:invalid list index -1 (index must be non-negative)), e6: _|_([]:index 1 out of bounds), def: <1>{a: 1, b :: 3}, e7: _|_(<2>.def["b"]:field "b" is a definition)}
diff --git a/cue/testdata/resolve/017_disjunctions of lists.txtar b/cue/testdata/resolve/017_disjunctions of lists.txtar
new file mode 100644
index 0000000..896fef7
--- /dev/null
+++ b/cue/testdata/resolve/017_disjunctions of lists.txtar
@@ -0,0 +1,15 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: disjunctions of lists
+#evalPartial
+-- in.cue --
+l: [ int, int] | [ string, string]
+
+l1: [ "a", "b"]
+l2: l & [ "c", "d"]
+-- out/def --
+l: [int, int] | [string, string]
+l1: ["a", "b"]
+l2: ["c", "d"]
+-- out/legacy-debug --
+<0>{l: ([int,int] | [string,string]), l1: ["a","b"], l2: ["c","d"]}
diff --git a/cue/testdata/resolve/018_slice.txtar b/cue/testdata/resolve/018_slice.txtar
new file mode 100644
index 0000000..560299f
--- /dev/null
+++ b/cue/testdata/resolve/018_slice.txtar
@@ -0,0 +1,26 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: slice
+#evalPartial
+-- in.cue --
+a:  [2][0:0]
+b:  [0][1:1]
+e1: [][1:1]
+e2: [0][-1:0]
+e3: [0][1:0]
+e4: [0][1:2]
+e5: 4[1:2]
+e6: [2]["":]
+e7: [2][:"9"]
+-- out/def --
+a: []
+b: []
+e1: _|_ // slice bounds out of range
+e2: _|_ // negative slice index
+e3: _|_ // invalid slice index: 1 > 0
+e4: _|_ // slice bounds out of range
+e5: _|_ // cannot slice 4 (type int)
+e6: _|_ // invalid slice index "" (type string)
+e7: _|_ // invalid slice index "9" (type string)
+-- out/legacy-debug --
+<0>{a: [], b: [], e1: _|_(1:slice bounds out of range), e2: _|_([0]:negative slice index), e3: _|_([0]:invalid slice index: 1 > 0), e4: _|_(2:slice bounds out of range), e5: _|_(4:cannot slice 4 (type int)), e6: _|_("":invalid slice index "" (type string)), e7: _|_("9":invalid slice index "9" (type string))}
diff --git a/cue/testdata/resolve/019_list types.txtar b/cue/testdata/resolve/019_list types.txtar
new file mode 100644
index 0000000..1370d51
--- /dev/null
+++ b/cue/testdata/resolve/019_list types.txtar
@@ -0,0 +1,50 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: list types
+#evalPartial
+-- in.cue --
+l0: 3 * [int]
+l0: [1, 2, 3]
+l2: [...{a: int}]
+l2: [{a: 1}, {a: 2, b: 3}]
+
+// TODO: work out a decent way to specify length ranges of lists.
+// l3: <=10*[int]
+// l3: [1, 2, 3, ...]
+
+s1: (6 * [int])[2:3]
+s2: [0, 2, 3][1:2]
+
+i1: (6 * [int])[2]
+i2: [0, 2, 3][2]
+
+t0: [...{a: 8}]
+t0: [{}]
+t1: [...]
+t1: [...int]
+
+e0: 2 * [{}]
+e0: [{}]
+e1: [...int]
+e1: [...float]
+-- out/def --
+l0: [1, 2, 3]
+l2: [{
+	a: 1
+}, {
+	a: 2
+	b: 3
+}]
+s1: [int]
+s2: [2]
+i1: [int, int, int, int, int, int][2]
+i2: 3
+t0: [{
+	a: 8
+}]
+t1: [...int]
+e0: _|_ // conflicting list lengths: conflicting values 2 and 1
+e1: [..._|_ // conflicting values int and float (mismatched types int and float),
+]
+-- out/legacy-debug --
+<0>{l0: [1,2,3], l2: [<1>{a: 1},<2>{a: 2, b: 3}], s1: [int], s2: [2], i1: int, i2: 3, t0: [<3>{a: 8}], t1: [, ...int], e0: _|_(([<4>{},<4>{}] & [<5>{}]):conflicting list lengths: conflicting values 2 and 1), e1: [, ..._|_((int & float):conflicting values int and float (mismatched types int and float))]}
diff --git a/cue/testdata/resolve/020_list arithmetic.txtar b/cue/testdata/resolve/020_list arithmetic.txtar
new file mode 100644
index 0000000..e8d521f
--- /dev/null
+++ b/cue/testdata/resolve/020_list arithmetic.txtar
@@ -0,0 +1,100 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: list arithmetic
+#evalPartial
+-- in.cue --
+l0: 3 * [1, 2, 3]
+l1: 0 * [1, 2, 3]
+l2: 10 * []
+l3: <=2 * []
+l4: <=2 * [int]
+l5: <=2 * (int * [int])
+l6: 3 * [...int]
+l7: 3 * [1, ...int]
+l8: 3 * [1, 2, ...int]
+
+s0:  [] + []
+s1:  [1] + []
+s2:  [] + [2]
+s3:  [1] + [2]
+s4:  [1, 2] + []
+s5:  [] + [1, 2]
+s6:  [1] + [1, 2]
+s7:  [1, 2] + [1]
+s8:  [1, 2] + [1, 2]
+s9:  [] + [...]
+s10: [1] + [...]
+s11: [] + [2, ...]
+s12: [1] + [2, ...]
+s13: [1, 2] + [...]
+s14: [] + [1, 2, ...]
+s15: [1] + [1, 2, ...]
+s16: [1, 2] + [1, ...]
+s17: [1, 2] + [1, 2, ...]
+
+s18: [...] + []
+s19: [1, ...] + []
+s20: [...] + [2]
+s21: [1, ...] + [2]
+s22: [1, 2, ...] + []
+s23: [...] + [1, 2]
+s24: [1, ...] + [1, 2]
+s25: [1, 2, ...] + [1]
+s26: [1, 2, ...] + [1, 2]
+s27: [...] + [...]
+s28: [1, ...] + [...]
+s29: [...] + [2, ...]
+s30: [1, ...] + [2, ...]
+s31: [1, 2, ...] + [...]
+s32: [...] + [1, 2, ...]
+s33: [1, ...] + [1, 2, ...]
+s34: [1, 2, ...] + [1, ...]
+s35: [1, 2, ...] + [1, 2, ...]
+-- out/def --
+l0: [1, 2, 3, 1, 2, 3, 1, 2, 3]
+l1: []
+l2: []
+l3: <=2 * []
+l4: <=2 * [int]
+l5: <=2 * (int * [int])
+l6: []
+l7: [1, 1, 1]
+l8: [1, 2, 1, 2, 1, 2]
+s0: []
+s1: [1]
+s2: [2]
+s3: [1, 2]
+s4: [1, 2]
+s5: [1, 2]
+s6: [1, 1, 2]
+s7: [1, 2, 1]
+s8: [1, 2, 1, 2]
+s9: []
+s10: [1]
+s11: [2]
+s12: [1, 2]
+s13: [1, 2]
+s14: [1, 2]
+s15: [1, 1, 2]
+s16: [1, 2, 1]
+s17: [1, 2, 1, 2]
+s18: []
+s19: [1]
+s20: [2]
+s21: [1, 2]
+s22: [1, 2]
+s23: [1, 2]
+s24: [1, 1, 2]
+s25: [1, 2, 1]
+s26: [1, 2, 1, 2]
+s27: []
+s28: [1]
+s29: [2]
+s30: [1, 2]
+s31: [1, 2]
+s32: [1, 2]
+s33: [1, 1, 2]
+s34: [1, 2, 1]
+s35: [1, 2, 1, 2]
+-- out/legacy-debug --
+<0>{l0: [1,2,3,1,2,3,1,2,3], l1: [], l2: [], l3: (<=2 * []), l4: (<=2 * [int]), l5: (<=2 * (int * [int])), l6: [], l7: [1,1,1], l8: [1,2,1,2,1,2], s0: [], s1: [1], s2: [2], s3: [1,2], s4: [1,2], s5: [1,2], s6: [1,1,2], s7: [1,2,1], s8: [1,2,1,2], s9: [], s10: [1], s11: [2], s12: [1,2], s13: [1,2], s14: [1,2], s15: [1,1,2], s16: [1,2,1], s17: [1,2,1,2], s18: [], s19: [1], s20: [2], s21: [1,2], s22: [1,2], s23: [1,2], s24: [1,1,2], s25: [1,2,1], s26: [1,2,1,2], s27: [], s28: [1], s29: [2], s30: [1,2], s31: [1,2], s32: [1,2], s33: [1,1,2], s34: [1,2,1], s35: [1,2,1,2]}
diff --git a/cue/testdata/resolve/021_list equality.txtar b/cue/testdata/resolve/021_list equality.txtar
new file mode 100644
index 0000000..ecc8e59
--- /dev/null
+++ b/cue/testdata/resolve/021_list equality.txtar
@@ -0,0 +1,215 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: list equality
+#evalPartial
+-- in.cue --
+eq0: [] == []
+eq1: [...] == []
+eq2: [] == [...]
+eq3: [...] == [...]
+
+eq4: [1] == [1]
+eq5: [1, ...] == [1]
+eq6: [1] == [1, ...]
+eq7: [1, ...] == [1, ...]
+
+eq8:  [1, 2] == [1, 2]
+eq9:  [1, 2, ...] == [1, 2]
+eq10: [1, 2] == [1, 2, ...]
+eq11: [1, 2, ...] == [1, 2, ...]
+
+ne0: [] != []
+ne1: [...] != []
+ne2: [] != [...]
+ne3: [...] != [...]
+
+ne4: [1] != [1]
+ne5: [1, ...] != [1]
+ne6: [1] != [1, ...]
+ne7: [1, ...] != [1, ...]
+
+ne8:  [1, 2] != [1, 2]
+ne9:  [1, 2, ...] != [1, 2]
+ne10: [1, 2] != [1, 2, ...]
+ne11: [1, 2, ...] != [1, 2, ...]
+
+feq0: [] == [1]
+feq1: [...] == [1]
+feq2: [] == [1, ...]
+feq3: [...] == [1, ...]
+
+feq4: [1] == []
+feq5: [1, ...] == []
+feq6: [1] == [...]
+feq7: [1, ...] == [...]
+
+feq8:  [1, 2] == [1]
+feq9:  [1, ...] == [1, 2]
+feq10: [1, 2] == [1, ...]
+feq11: [1, ...] == [1, 2, ...]
+
+fne0: [] != [1]
+fne1: [...] != [1]
+fne2: [] != [1, ...]
+fne3: [1, ...] != [1, ...]
+
+fne4: [1] != []
+fne5: [1, ...] != []
+fne6: [1] != [...]
+fne7: [1, ...] != [...]
+
+fne8:  [1, 2] != [1]
+fne9:  [1, ...] != [1, 2]
+fne10: [1, 2] != [1, ...]
+fne11: [1, ...] != [1, 2, ...]
+-- out/def --
+eq0:   true
+eq1:   true
+eq2:   true
+eq3:   true
+eq4:   true
+eq5:   true
+eq6:   true
+eq7:   true
+eq8:   true
+eq9:   true
+eq10:  true
+eq11:  true
+ne0:   true
+ne1:   true
+ne2:   true
+ne3:   true
+ne4:   false
+ne5:   false
+ne6:   false
+ne7:   false
+ne8:   false
+ne9:   false
+ne10:  false
+ne11:  false
+feq0:  false
+feq1:  false
+feq2:  false
+feq3:  false
+feq4:  false
+feq5:  false
+feq6:  false
+feq7:  false
+feq8:  false
+feq9:  false
+feq10: false
+feq11: false
+fne0:  false
+fne1:  false
+fne2:  false
+fne3:  false
+fne4:  false
+fne5:  false
+fne6:  false
+fne7:  false
+fne8:  false
+fne9:  false
+fne10: false
+fne11: false
+-- out/export --
+eq0:   true
+eq1:   true
+eq2:   true
+eq3:   true
+eq4:   true
+eq5:   true
+eq6:   true
+eq7:   true
+eq8:   true
+eq9:   true
+eq10:  true
+eq11:  true
+ne0:   true
+ne1:   true
+ne2:   true
+ne3:   true
+ne4:   false
+ne5:   false
+ne6:   false
+ne7:   false
+ne8:   false
+ne9:   false
+ne10:  false
+ne11:  false
+feq0:  false
+feq1:  false
+feq2:  false
+feq3:  false
+feq4:  false
+feq5:  false
+feq6:  false
+feq7:  false
+feq8:  false
+feq9:  false
+feq10: false
+feq11: false
+fne0:  false
+fne1:  false
+fne2:  false
+fne3:  false
+fne4:  false
+fne5:  false
+fne6:  false
+fne7:  false
+fne8:  false
+fne9:  false
+fne10: false
+fne11: false
+-- out/yaml --
+eq0: true
+eq1: true
+eq2: true
+eq3: true
+eq4: true
+eq5: true
+eq6: true
+eq7: true
+eq8: true
+eq9: true
+eq10: true
+eq11: true
+ne0: true
+ne1: true
+ne2: true
+ne3: true
+ne4: false
+ne5: false
+ne6: false
+ne7: false
+ne8: false
+ne9: false
+ne10: false
+ne11: false
+feq0: false
+feq1: false
+feq2: false
+feq3: false
+feq4: false
+feq5: false
+feq6: false
+feq7: false
+feq8: false
+feq9: false
+feq10: false
+feq11: false
+fne0: false
+fne1: false
+fne2: false
+fne3: false
+fne4: false
+fne5: false
+fne6: false
+fne7: false
+fne8: false
+fne9: false
+fne10: false
+fne11: false
+-- out/json --
+{"eq0":true,"eq1":true,"eq2":true,"eq3":true,"eq4":true,"eq5":true,"eq6":true,"eq7":true,"eq8":true,"eq9":true,"eq10":true,"eq11":true,"ne0":true,"ne1":true,"ne2":true,"ne3":true,"ne4":false,"ne5":false,"ne6":false,"ne7":false,"ne8":false,"ne9":false,"ne10":false,"ne11":false,"feq0":false,"feq1":false,"feq2":false,"feq3":false,"feq4":false,"feq5":false,"feq6":false,"feq7":false,"feq8":false,"feq9":false,"feq10":false,"feq11":false,"fne0":false,"fne1":false,"fne2":false,"fne3":false,"fne4":false,"fne5":false,"fne6":false,"fne7":false,"fne8":false,"fne9":false,"fne10":false,"fne11":false}
+-- out/legacy-debug --
+<0>{eq0: true, eq1: true, eq2: true, eq3: true, eq4: true, eq5: true, eq6: true, eq7: true, eq8: true, eq9: true, eq10: true, eq11: true, ne0: true, ne1: true, ne2: true, ne3: true, ne4: false, ne5: false, ne6: false, ne7: false, ne8: false, ne9: false, ne10: false, ne11: false, feq0: false, feq1: false, feq2: false, feq3: false, feq4: false, feq5: false, feq6: false, feq7: false, feq8: false, feq9: false, feq10: false, feq11: false, fne0: false, fne1: false, fne2: false, fne3: false, fne4: false, fne5: false, fne6: false, fne7: false, fne8: false, fne9: false, fne10: false, fne11: false}
diff --git a/cue/testdata/resolve/022_list unification.txtar b/cue/testdata/resolve/022_list unification.txtar
new file mode 100644
index 0000000..abb794b
--- /dev/null
+++ b/cue/testdata/resolve/022_list unification.txtar
@@ -0,0 +1,17 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: list unification
+#evalPartial
+-- in.cue --
+a: {l: ["foo", v], v: l[1]}
+b: a & {l: [_, "bar"]}
+-- out/def --
+a: {
+	l: ["foo", v]
+	v: l[1]
+}
+b: a & {
+	l: [_, "bar"]
+}
+-- out/legacy-debug --
+<0>{a: <1>{l: ["foo",<2>.v], v: <2>.l[1]}, b: <3>{l: ["foo","bar"], v: "bar"}}
diff --git a/cue/testdata/resolve/023_correct error messages.txtar b/cue/testdata/resolve/023_correct error messages.txtar
new file mode 100644
index 0000000..28f8089
--- /dev/null
+++ b/cue/testdata/resolve/023_correct error messages.txtar
@@ -0,0 +1,10 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: correct error messages
+#evalPartial
+-- in.cue --
+a: "a" & 1
+-- out/def --
+a: _|_ // conflicting values "a" and 1 (mismatched types string and int)
+-- out/legacy-debug --
+<0>{a: _|_(("a" & 1):conflicting values "a" and 1 (mismatched types string and int))}
diff --git a/cue/testdata/resolve/024_structs.txtar b/cue/testdata/resolve/024_structs.txtar
new file mode 100644
index 0000000..48d1e33
--- /dev/null
+++ b/cue/testdata/resolve/024_structs.txtar
@@ -0,0 +1,25 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: structs
+#evalPartial
+-- in.cue --
+a: t & {c:  5} // {c:5,d:15}
+b: ti & {c: 7} // {c:7,d:21}
+t: {c: number, d: c * 3} // {c:number,d:number*3}
+ti: t & {c: int}
+-- out/def --
+a: t & {
+	c: 5
+}
+t: {
+	c: number
+	d: c * 3
+}
+b: ti & {
+	c: 7
+}
+ti: t & {
+	c: int
+}
+-- out/legacy-debug --
+<0>{a: <1>{c: 5, d: 15}, t: <2>{c: number, d: (<3>.c * 3)}, b: <4>{c: 7, d: 21}, ti: <5>{c: int, d: (<6>.c * 3)}}
diff --git a/cue/testdata/resolve/025_definitions.txtar b/cue/testdata/resolve/025_definitions.txtar
new file mode 100644
index 0000000..ec38bd5
--- /dev/null
+++ b/cue/testdata/resolve/025_definitions.txtar
@@ -0,0 +1,70 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: definitions
+#evalPartial
+-- in.cue --
+Foo :: {
+	field: int
+	recursive: {
+		field: string
+	}
+}
+
+// Allowed
+Foo1 :: {field: int}
+Foo1 :: {field2: string}
+
+foo: Foo
+foo: {feild: 2}
+
+foo1: Foo
+foo1: {
+	field: 2
+	recursive: {
+		feild: 2 // Not caught as per spec. TODO: change?
+	}
+}
+
+Bar :: {
+	field: int
+	{[A=_]: int}
+}
+bar: Bar
+bar: {feild: 2}
+
+Mixed :: string
+Mixed:   string
+
+mixedRec: {Mixed :: string}
+mixedRec: {Mixed: string}
+-- out/def --
+Foo :: {
+	field: int
+	recursive: {
+		field: string
+	}
+}
+
+// Allowed
+Foo1 :: {
+	field:  int
+	field2: string
+}
+foo:  _|_ // field "feild" not allowed in closed struct
+foo1: Foo & {
+	field: 2
+	recursive: {
+		feild: 2
+	}
+}
+Bar :: {
+	{[A=string]: int}
+	field: int
+}
+bar: Bar & {
+	feild: 2
+}
+Mixed:    _|_ // field "Mixed" declared as definition and regular field
+mixedRec: _|_ // field "Mixed" declared as definition and regular field
+-- out/legacy-debug --
+<0>{Foo :: <1>C{field: int, recursive: <2>C{field: string}}, Foo1 :: <3>C{field: int, field2: string}, foo: _|_(2:field "feild" not allowed in closed struct), foo1: <4>C{field: 2, recursive: _|_(2:field "feild" not allowed in closed struct)}, Bar :: <5>{[]: <6>(A: string)->int, field: int}, bar: <7>{[]: <8>(A: string)->int, field: int, feild: 2}, Mixed: _|_(field "Mixed" declared as definition and regular field), mixedRec: _|_(field "Mixed" declared as definition and regular field)}
diff --git a/cue/testdata/resolve/026_combined definitions.txtar b/cue/testdata/resolve/026_combined definitions.txtar
new file mode 100644
index 0000000..79d39df
--- /dev/null
+++ b/cue/testdata/resolve/026_combined definitions.txtar
@@ -0,0 +1,70 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: combined definitions
+#evalPartial
+-- in.cue --
+// Allow combining of structs within a definition
+D1 :: {
+	env: a: "A"
+	env: b: "B"
+	def :: {a: "A"}
+	def :: {b: "B"}
+}
+
+d1: D1 & {env: c: "C"}
+
+D2 :: {
+	a: int
+}
+D2 :: {
+	b: int
+}
+
+D3 :: {
+	env: a: "A"
+}
+D3 :: {
+	env: b: "B"
+}
+
+D4 :: {
+	env: DC
+	env: b: int
+}
+
+DC :: {a: int}
+-- out/def --
+// Allow combining of structs within a definition
+D1 :: {
+	env: {
+		a: "A"
+		b: "B"
+	}
+	def :: {
+		a: "A"
+		b: "B"
+	}
+}
+d1: D1 & {
+	env: {
+		c: "C"
+	}
+}
+D2 :: {
+	a: int
+	b: int
+}
+D3 :: {
+	env: {
+		a: "A"
+		b: "B"
+	}
+}
+D4 :: {
+	env: _|_ // field "b" not allowed in closed struct
+}
+DC :: {
+	a: int
+}
+-- out/legacy-debug --
+<0>{D1 :: <1>C{env: <2>C{a: "A", b: "B"}, def :: <3>C{a: "A", b: "B"}}, d1: <4>C{env: _|_("C":field "c" not allowed in closed struct), def :: <5>C{a: "A", b: "B"}}, D2 :: <6>C{a: int, b: int}, D3 :: <7>C{env: <8>C{a: "A", b: "B"}}, D4 :: <9>C{env: _|_(int:field "b" not allowed in closed struct)}, DC :: <10>C{a: int}}
diff --git a/cue/testdata/resolve/027_new-style definitions.txtar b/cue/testdata/resolve/027_new-style definitions.txtar
new file mode 100644
index 0000000..511ff3c
--- /dev/null
+++ b/cue/testdata/resolve/027_new-style definitions.txtar
@@ -0,0 +1,48 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: new-style definitions
+#evalPartial
+-- in.cue --
+#Foo: {
+	a: 1
+	b: int
+}
+"#Foo": #Foo & {b: 1}
+
+bulk: {[string]: string} & {
+	#def: 4 // Different namespace, so bulk option does not apply.
+	_hid: 3
+	a:    "foo"
+}
+-- out/def --
+"#Foo": #Foo & {
+	b: 1
+}
+#Foo: {
+	a: 1
+	b: int
+}
+bulk: {
+	{[string]: string}
+	a:    "foo"
+	#def: 4
+	_hid: 3
+}
+-- out/export --
+"#Foo": {
+	a: 1
+	b: 1
+}
+bulk: {
+	a: "foo"
+}
+-- out/yaml --
+'#Foo':
+  a: 1
+  b: 1
+bulk:
+  a: foo
+-- out/json --
+{"#Foo":{"a":1,"b":1},"bulk":{"a":"foo"}}
+-- out/legacy-debug --
+<0>{"#Foo": <1>C{a: 1, b: 1}, #Foo: <2>C{a: 1, b: int}, bulk: <3>{[]: <4>(_: string)->string, a: "foo", #def: 4, _hid: 3}}
diff --git a/cue/testdata/resolve/028_recursive closing starting at non-definition.txtar b/cue/testdata/resolve/028_recursive closing starting at non-definition.txtar
new file mode 100644
index 0000000..0695609
--- /dev/null
+++ b/cue/testdata/resolve/028_recursive closing starting at non-definition.txtar
@@ -0,0 +1,48 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: recursive closing starting at non-definition
+#evalPartial
+-- in.cue --
+z: a: {
+	B :: {
+		c: d: 1
+		c: f: 1
+	}
+}
+A: z & {a: {B :: {c: e: 2}}}
+-- out/def --
+z: {
+	a: {
+		B :: {
+			c: {
+				d: 1
+				f: 1
+			}
+		}
+	}
+}
+A: z & {
+	a: {
+		B :: {
+			c: {
+				e: 2
+			}
+		}
+	}
+}
+-- out/export --
+z: {
+	a: {}
+}
+A: {
+	a: {}
+}
+-- out/yaml --
+z:
+  a: {}
+A:
+  a: {}
+-- out/json --
+{"z":{"a":{}},"A":{"a":{}}}
+-- out/legacy-debug --
+<0>{z: <1>{a: <2>{B :: <3>C{c: <4>C{d: 1, f: 1}}}}, A: <5>{a: <6>{B :: <7>C{c: _|_(2:field "e" not allowed in closed struct)}}}}
diff --git a/cue/testdata/resolve/029_non-closed definition carries over closedness to enclosed template.txtar b/cue/testdata/resolve/029_non-closed definition carries over closedness to enclosed template.txtar
new file mode 100644
index 0000000..b9dca9c
--- /dev/null
+++ b/cue/testdata/resolve/029_non-closed definition carries over closedness to enclosed template.txtar
@@ -0,0 +1,60 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: non-closed definition carries over closedness to enclosed template
+#evalPartial
+-- in.cue --
+S :: {
+	[string]: {a: int}
+}
+a: S & {
+	v: {b: int}
+}
+Q :: {
+	[string]: {a: int} | {b: int}
+}
+b: Q & {
+	w: {c: int}
+}
+R :: {
+	[string]: [{a: int}, {b: int}]
+}
+c: R & {
+	w: [{d: int}, ...]
+}
+-- out/def --
+S :: {
+	[string]: {
+		a: int
+	}
+}
+a: S & {
+	v: {
+		b: int
+	}
+}
+b: Q & {
+	w: {
+		c: int
+	}
+}
+Q :: {
+	[string]: {
+		a: int
+	} | {
+		b: int
+	}
+}
+c: R & {
+	w: [{
+		d: int
+	}, ...]
+}
+R :: {
+	[string]: [{
+		a: int
+	}, {
+		b: int
+	}]
+}
+-- out/legacy-debug --
+<0>{S :: <1>{[]: <2>(_: string)-><3>C{a: int}, }, a: <4>{[]: <5>(_: string)-><6>C{a: int}, v: _|_(int:field "b" not allowed in closed struct)}, b: <7>{[]: <8>(_: string)->(<9>C{a: int} | <10>C{b: int}), w: _|_(int:empty disjunction: field "c" not allowed in closed struct)}, Q :: <11>{[]: <12>(_: string)->(<13>C{a: int} | <14>C{b: int}), }, c: <15>{[]: <16>(_: string)->[<17>C{a: int},<18>C{b: int}], w: [_|_(int:field "d" not allowed in closed struct),<19>C{b: int}]}, R :: <20>{[]: <21>(_: string)->[<22>C{a: int},<23>C{b: int}], }}
diff --git a/cue/testdata/resolve/030_definitions with disjunctions.txtar b/cue/testdata/resolve/030_definitions with disjunctions.txtar
new file mode 100644
index 0000000..7baaff1
--- /dev/null
+++ b/cue/testdata/resolve/030_definitions with disjunctions.txtar
@@ -0,0 +1,37 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: definitions with disjunctions
+#evalPartial
+-- in.cue --
+Foo :: {
+	field: int
+
+	{a: 1} |
+	{b: 2}
+}
+
+foo: Foo
+foo: {a: 1}
+
+bar: Foo
+bar: {c: 2}
+
+baz: Foo
+baz: {b: 2}
+-- out/def --
+Foo :: {
+	field: int
+	a:     1
+} | {
+	field: int
+	b:     2
+}
+foo: Foo & {
+	a: 1
+}
+bar: _|_ // 
+baz: Foo & {
+	b: 2
+}
+-- out/legacy-debug --
+<0>{Foo :: (<1>C{field: int, a: 1} | <2>C{field: int, b: 2}), foo: <3>C{field: int, a: 1}, bar: _|_(2:empty disjunction: field "c" not allowed in closed struct), baz: <4>C{field: int, b: 2}}
diff --git a/cue/testdata/resolve/031_definitions with disjunctions recurisive.txtar b/cue/testdata/resolve/031_definitions with disjunctions recurisive.txtar
new file mode 100644
index 0000000..cc701ff
--- /dev/null
+++ b/cue/testdata/resolve/031_definitions with disjunctions recurisive.txtar
@@ -0,0 +1,34 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: definitions with disjunctions recurisive
+#evalPartial
+-- in.cue --
+Foo :: {
+	x: {
+		field: int
+
+		{a: 1} |
+		{b: 2}
+	}
+	x: c: 3
+}
+-- out/def --
+Foo :: {
+	x: {
+		field: int
+		a:     1
+		c:     3
+	} | {
+		field: int
+		b:     2
+		c:     3
+	}
+}
+-- out/export --
+
+-- out/yaml --
+{}
+-- out/json --
+{}
+-- out/legacy-debug --
+<0>{Foo :: <1>C{x: (<2>C{field: int, a: 1, c: 3} | <3>C{field: int, b: 2, c: 3})}}
diff --git a/cue/testdata/resolve/032_definitions with embedding.txtar b/cue/testdata/resolve/032_definitions with embedding.txtar
new file mode 100644
index 0000000..71bd870
--- /dev/null
+++ b/cue/testdata/resolve/032_definitions with embedding.txtar
@@ -0,0 +1,55 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: definitions with embedding
+#evalPartial
+-- in.cue --
+E :: {
+	a: {b: int}
+}
+
+S :: {
+	E
+	a: {c: int}
+	b: 3
+}
+
+// adding a field to a nested struct that is closed.
+e1 :: S & {a: d: 4}
+
+// literal struct not closed until after unification.
+v1 :: S & {a: c: 4}
+-- out/def --
+E :: {
+	a: {
+		b: int
+	}
+}
+S :: {
+	a: {
+		c: int
+	}
+	b: 3
+	E
+}
+
+// adding a field to a nested struct that is closed.
+e1 :: S & {
+	a: {
+		d: 4
+	}
+}
+
+// literal struct not closed until after unification.
+v1 :: S & {
+	a: {
+		c: 4
+	}
+}
+-- out/export --
+
+-- out/yaml --
+{}
+-- out/json --
+{}
+-- out/legacy-debug --
+<0>{E :: <1>C{a: <2>C{b: int}}, S :: <3>C{a: <4>C{b: int, c: int}, b: 3}, e1 :: <5>C{a: _|_(4:field "d" not allowed in closed struct), b: 3}, v1 :: <6>C{a: <7>C{b: int, c: 4}, b: 3}}
diff --git a/cue/testdata/resolve/033_top-level definition with struct and disjunction.txtar b/cue/testdata/resolve/033_top-level definition with struct and disjunction.txtar
new file mode 100644
index 0000000..eeb8159
--- /dev/null
+++ b/cue/testdata/resolve/033_top-level definition with struct and disjunction.txtar
@@ -0,0 +1,36 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: top-level definition with struct and disjunction
+#evalPartial
+-- in.cue --
+def :: {
+	Type: string
+	Text: string
+	Size: int
+}
+
+def :: {
+	Type: "B"
+	Size: 0
+} | {
+	Type: "A"
+	Size: 1
+}
+-- out/def --
+def :: {
+	Size: 0
+	Type: "B"
+	Text: string
+} | {
+	Size: 1
+	Type: "A"
+	Text: string
+}
+-- out/export --
+
+-- out/yaml --
+{}
+-- out/json --
+{}
+-- out/legacy-debug --
+<0>{def :: (<1>C{Size: (0 & int), Type: ("B" & string), Text: string} | <2>C{Size: (1 & int), Type: ("A" & string), Text: string})}
diff --git a/cue/testdata/resolve/034_closing structs.txtar b/cue/testdata/resolve/034_closing structs.txtar
new file mode 100644
index 0000000..7bf10e0
--- /dev/null
+++ b/cue/testdata/resolve/034_closing structs.txtar
@@ -0,0 +1,53 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: closing structs
+#evalPartial
+-- in.cue --
+op: {x: int} // {x: int}
+ot: {x: int, ...} // {x: int, ...}
+cp: close({x: int})      // closed({x: int})
+ct: close({x: int, ...}) // {x: int, ...}
+
+opot: op & ot // {x: int, ...}
+otop: ot & op // {x: int, ...}
+opcp: op & cp // closed({x: int})
+cpop: cp & op // closed({x: int})
+opct: op & ct // {x: int, ...}
+ctop: ct & op // {x: int, ...}
+otcp: ot & cp // closed({x: int})
+cpot: cp & ot // closed({x: int})
+otct: ot & ct // {x: int, ...}
+ctot: ct & ot // {x: int, ...}
+cpct: cp & ct // closed({x: int})
+ctcp: ct & cp // closed({x: int})
+ctct: ct & ct // {x: int, ...}
+-- out/def --
+op: {
+	x: int
+}
+ot: {
+	x: int
+	...
+}
+cp: close({
+	x: int
+})
+ct: {
+	x: int
+	...
+}
+opot: op & ot
+otop: ot & op
+opcp: op & cp
+cpop: cp & op
+opct: op & ct
+ctop: ct & op
+otcp: ot & cp
+cpot: cp & ot
+otct: ot & ct
+ctot: ct & ot
+cpct: cp & ct
+ctcp: ct & cp
+ctct: ct & ct
+-- out/legacy-debug --
+<0>{op: <1>{x: int}, ot: <2>{x: int, ...}, cp: <3>C{x: int}, ct: <4>{x: int, ...}, opot: <5>{x: int, ...}, otop: <6>{x: int, ...}, opcp: <7>C{x: int}, cpop: <8>C{x: int}, opct: <9>{x: int, ...}, ctop: <10>{x: int, ...}, otcp: <11>C{x: int}, cpot: <12>C{x: int}, otct: <13>{x: int, ...}, ctot: <14>{x: int, ...}, cpct: <15>C{x: int}, ctcp: <16>C{x: int}, ctct: <17>{x: int, ...}}
diff --git a/cue/testdata/resolve/035_excluded embedding from closing.txtar b/cue/testdata/resolve/035_excluded embedding from closing.txtar
new file mode 100644
index 0000000..7db5d93
--- /dev/null
+++ b/cue/testdata/resolve/035_excluded embedding from closing.txtar
@@ -0,0 +1,41 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: excluded embedding from closing
+#evalPartial
+-- in.cue --
+S :: {
+	a: {c: int}
+	{
+		c: {d: int}
+	}
+	B = {open: int}
+	b: B
+}
+V: S & {
+	c: e:     int
+	b: extra: int
+}
+-- out/def --
+S :: {
+	a: {
+		c: int
+	}
+	c: {
+		d: int
+		...
+	}
+	b: {
+		open: int
+		...
+	}
+}
+V: S & {
+	c: {
+		e: int
+	}
+	b: {
+		extra: int
+	}
+}
+-- out/legacy-debug --
+<0>{S :: <1>C{a: <2>C{c: int}, c: <3>{d: int}, b: <4>{open: int}}, V: <5>C{a: <6>C{c: int}, c: <7>{d: int, e: int}, b: <8>{open: int, extra: int}}}
diff --git a/cue/testdata/resolve/036_closing with failed optional.txtar b/cue/testdata/resolve/036_closing with failed optional.txtar
new file mode 100644
index 0000000..2473f54
--- /dev/null
+++ b/cue/testdata/resolve/036_closing with failed optional.txtar
@@ -0,0 +1,63 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: closing with failed optional
+#evalPartial
+-- in.cue --
+k1 :: {a: int, b?: int} & A // closed({a: int})
+
+k2 :: A & {a: int, b?: int} // closed({a: int})
+
+o1: {a?: 3} & {a?: 4} // {a?: _|_}
+
+// Optional fields with error values can be elimintated when closing
+o2 :: {a?: 3} & {a?: 4} // close({})
+
+d1 :: {a?: 2, b: 4} | {a?: 3, c: 5}
+
+v1: d1 & {a?: 3, b: 4} // close({b: 4})
+
+A :: {a: int}
+-- out/def --
+k1 :: {
+	a:  int
+	b?: int
+} & A
+A :: {
+	a: int
+}
+k2 :: A & {
+	a:  int
+	b?: int
+}
+o1: {
+	a?: _|_ // conflicting values 3 and 4
+}
+
+// Optional fields with error values can be elimintated when closing
+o2 :: {
+	a?: _|_ // conflicting values 3 and 4
+}
+d1 :: {
+	a?: 2
+	b:  4
+} | {
+	a?: 3
+	c:  5
+}
+v1: d1 & {
+	a?: 3
+	b:  4
+}
+-- out/export --
+o1: {}
+v1: {
+	b: 4
+}
+-- out/yaml --
+o1: {}
+v1:
+  b: 4
+-- out/json --
+{"o1":{},"v1":{"b":4}}
+-- out/legacy-debug --
+<0>{k1 :: <1>C{a: int}, A :: <2>C{a: int}, k2 :: <3>C{a: int}, o1: <4>{a?: _|_((3 & 4):conflicting values 3 and 4)}, o2 :: <5>C{a?: _|_((3 & 4):conflicting values 3 and 4)}, d1 :: (<6>C{a?: 2, b: 4} | <7>C{a?: 3, c: 5}), v1: <8>C{a?: _|_((2 & 3):conflicting values 2 and 3), b: 4}}
diff --git a/cue/testdata/resolve/037_closing with comprehensions.txtar b/cue/testdata/resolve/037_closing with comprehensions.txtar
new file mode 100644
index 0000000..6167314
--- /dev/null
+++ b/cue/testdata/resolve/037_closing with comprehensions.txtar
@@ -0,0 +1,59 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: closing with comprehensions
+#evalPartial
+-- in.cue --
+A :: {f1: int, f2: int}
+
+for k, v in {f3: int} {
+	a: A & {"\(k)": v}
+}
+
+B :: {
+	for k, v in {f1: int} {
+		"\(k)": v
+	}
+}
+
+C :: {
+	f1: _
+	for k, v in {f1: int} {
+		"\(k)": v
+	}
+}
+
+D :: {
+	for k, v in {f1: int} {
+		"\(k)": v
+	}
+	...
+}
+
+E :: A & {
+	for k, v in {f3: int} {
+		"\(k)": v
+	}
+}
+-- out/def --
+E :: _|_ // field "f3" not allowed in closed struct
+A :: {
+	f1: int
+	f2: int
+}
+a: _|_ // field "f3" not allowed in closed struct
+B :: {
+	f1: v
+}
+C :: {
+	f1: {
+		_
+		v
+		...
+	}
+}
+D :: {
+	f1: v
+	...
+}
+-- out/legacy-debug --
+<0>{E :: _|_(<1>.v:field "f3" not allowed in closed struct), A :: <2>C{f1: int, f2: int}, a: _|_(<3>.v:field "f3" not allowed in closed struct), B :: <4>C{f1: int}, C :: <5>C{f1: int}, D :: <6>{f1: int, ...}}
diff --git a/cue/testdata/resolve/038_incomplete comprehensions.txtar b/cue/testdata/resolve/038_incomplete comprehensions.txtar
new file mode 100644
index 0000000..7cc7ab3
--- /dev/null
+++ b/cue/testdata/resolve/038_incomplete comprehensions.txtar
@@ -0,0 +1,30 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: incomplete comprehensions
+#evalPartial
+-- in.cue --
+A: {
+	for v in src {
+		"\(v)": v
+	}
+	src: _
+	if true {
+		baz: "baz"
+	}
+}
+B: A & {
+	src: ["foo", "bar"]
+}
+-- out/def --
+A: {
+	src: _
+	baz: "baz"
+	for v in src {
+		"\(v)": v
+	}
+}
+B: A & {
+	src: ["foo", "bar"]
+}
+-- out/legacy-debug --
+<0>{A: <1>{src: _, baz: "baz" <2>for _, v in <3>.src yield <4>{""+<2>.v+"": <2>.v}}, B: <5>{src: ["foo","bar"], baz: "baz", foo: "foo", bar: "bar"}}
diff --git a/cue/testdata/resolve/039_reference to root.txtar b/cue/testdata/resolve/039_reference to root.txtar
new file mode 100644
index 0000000..18a63e8
--- /dev/null
+++ b/cue/testdata/resolve/039_reference to root.txtar
@@ -0,0 +1,51 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: reference to root
+#evalPartial
+-- in.cue --
+a: {b: int}
+c: a & {
+	b: 100
+	d: a.b + 3 // do not resolve as c != a.
+}
+x: {
+	b: int
+	c: b + 5
+}
+y: x & {
+	b: 100
+	// c should resolve to 105
+}
+v: {
+	b: int
+	c: v.b + 5 // reference starting from copied node.
+}
+w:  v & {b: 100}
+wp: v & {b: 100}
+-- out/def --
+x: {
+	b: int
+	c: b + 5
+}
+y: x & {
+	b: 100
+}
+a: {
+	b: int
+}
+c: a & {
+	b: 100
+	d: a.b + 3
+}
+v: {
+	b: int
+	c: v.b + 5
+}
+w: v & {
+	b: 100
+}
+wp: v & {
+	b: 100
+}
+-- out/legacy-debug --
+<0>{x: <1>{b: int, c: (<2>.b + 5)}, y: <3>{b: 100, c: 105}, a: <4>{b: int}, c: <5>{b: 100, d: (<6>.a.b + 3)}, v: <7>{b: int, c: (<6>.v.b + 5)}, w: <8>{b: 100, c: (<6>.v.b + 5)}, wp: <9>{b: 100, c: (<6>.v.b + 5)}}
diff --git a/cue/testdata/resolve/040_references from template to concrete.txtar b/cue/testdata/resolve/040_references from template to concrete.txtar
new file mode 100644
index 0000000..f3115a7
--- /dev/null
+++ b/cue/testdata/resolve/040_references from template to concrete.txtar
@@ -0,0 +1,64 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: references from template to concrete
+#evalPartial
+-- in.cue --
+res: [t]
+t: [X=string]: {
+	a: c + b.str
+	b: str: string
+	c: "X"
+}
+t: x: {b: str: "DDDD"}
+-- out/def --
+res: [t]
+t: {
+	{[X=string]: {
+		a: c + b.str, c: "X", b: {
+			str:          string
+		}
+	}}
+	x: {
+		a: "XDDDD"
+		c: "X"
+		b: {
+			str: "DDDD"
+		}
+	}
+}
+-- out/export --
+res: [{
+	x: {
+		a: "XDDDD"
+		c: "X"
+		b: {
+			str: "DDDD"
+		}
+	}
+}]
+t: {
+	x: {
+		a: "XDDDD"
+		c: "X"
+		b: {
+			str: "DDDD"
+		}
+	}
+}
+-- out/yaml --
+res:
+- x:
+    a: XDDDD
+    c: X
+    b:
+      str: DDDD
+t:
+  x:
+    a: XDDDD
+    c: X
+    b:
+      str: DDDD
+-- out/json --
+{"res":[{"x":{"a":"XDDDD","c":"X","b":{"str":"DDDD"}}}],"t":{"x":{"a":"XDDDD","c":"X","b":{"str":"DDDD"}}}}
+-- out/legacy-debug --
+<0>{res: [<1>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <5>{a: "XDDDD", c: "X", b: <6>{str: "DDDD"}}}], t: <7>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <8>{a: "XDDDD", c: "X", b: <9>{str: "DDDD"}}}}
diff --git a/cue/testdata/resolve/041_interpolation.txtar b/cue/testdata/resolve/041_interpolation.txtar
new file mode 100644
index 0000000..812be45
--- /dev/null
+++ b/cue/testdata/resolve/041_interpolation.txtar
@@ -0,0 +1,22 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: interpolation
+#evalPartial
+-- in.cue --
+a: "\(4)"
+b: "one \(a) two \( a+c )"
+c: "one"
+d: "\(r)"
+u: "\(_)"
+r: _
+e: "\([])"
+-- out/def --
+a: "4"
+b: "one 4 two 4one"
+c: "one"
+d: "\(r)"
+r: _
+u: "\(_)"
+e: _|_ // expression in interpolation must evaluate to a number kind or string (found list)
+-- out/legacy-debug --
+<0>{a: "4", b: "one 4 two 4one", c: "one", d: ""+<1>.r+"", r: _, u: ""+_+"", e: _|_([]:expression in interpolation must evaluate to a number kind or string (found list))}
diff --git a/cue/testdata/resolve/042_multiline interpolation.txtar b/cue/testdata/resolve/042_multiline interpolation.txtar
new file mode 100644
index 0000000..acab0cd
--- /dev/null
+++ b/cue/testdata/resolve/042_multiline interpolation.txtar
@@ -0,0 +1,165 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: multiline interpolation
+#evalPartial
+-- in.cue --
+a1: """
+			before
+			\(4)
+			after
+			"""
+a2: """
+			before
+			\(4)
+
+			"""
+a3: """
+
+			\(4)
+			after
+			"""
+a4: """
+
+			\(4)
+
+			"""
+m1: """
+			before
+			\(
+	4)
+			after
+			"""
+m2: """
+			before
+			\(
+	4)
+
+			"""
+m3: """
+
+			\(
+
+	4)
+			after
+			"""
+m4: """
+
+			\(
+	4)
+
+			"""
+-- out/def --
+a1: """
+        before
+        4
+        after
+        """
+a2: """
+        before
+        4
+        
+        """
+a3: """
+        
+        4
+        after
+        """
+a4: """
+        
+        4
+        
+        """
+m1: """
+        before
+        4
+        after
+        """
+m2: """
+        before
+        4
+        
+        """
+m3: """
+        
+        4
+        after
+        """
+m4: """
+        
+        4
+        
+        """
+-- out/export --
+a1: """
+        before
+        4
+        after
+        """
+a2: """
+        before
+        4
+        
+        """
+a3: """
+        
+        4
+        after
+        """
+a4: """
+        
+        4
+        
+        """
+m1: """
+        before
+        4
+        after
+        """
+m2: """
+        before
+        4
+        
+        """
+m3: """
+        
+        4
+        after
+        """
+m4: """
+        
+        4
+        
+        """
+-- out/yaml --
+a1: |-
+  before
+  4
+  after
+a2: |
+  before
+  4
+a3: |2-
+
+  4
+  after
+a4: |2
+
+  4
+m1: |-
+  before
+  4
+  after
+m2: |
+  before
+  4
+m3: |2-
+
+  4
+  after
+m4: |2
+
+  4
+-- out/json --
+{"a1":"before\n4\nafter","a2":"before\n4\n","a3":"\n4\nafter","a4":"\n4\n","m1":"before\n4\nafter","m2":"before\n4\n","m3":"\n4\nafter","m4":"\n4\n"}
+-- out/legacy-debug --
+<0>{a1: "before\n4\nafter", a2: "before\n4\n", a3: "\n4\nafter", a4: "\n4\n", m1: "before\n4\nafter", m2: "before\n4\n", m3: "\n4\nafter", m4: "\n4\n"}
diff --git a/cue/testdata/resolve/043_diamond-shaped constraints.txtar b/cue/testdata/resolve/043_diamond-shaped constraints.txtar
new file mode 100644
index 0000000..ac725a8
--- /dev/null
+++ b/cue/testdata/resolve/043_diamond-shaped constraints.txtar
@@ -0,0 +1,80 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: diamond-shaped constraints
+#evalPartial
+-- in.cue --
+S: {
+	A: {
+		a: 1
+	}
+	B: A & {
+		b: 2
+	}
+}
+T: S & {// S == { A: { a:1 }, B: { a:1, b:2 } }
+	A: {
+		c: 3
+	}
+	B: {
+		d: 4 // Combines constraints S.A, S.B, T.A, and T.B // S.B & A
+	}
+}
+-- out/def --
+T: S & {
+	A: {
+		c: 3
+	}
+	B: {
+		d: 4
+	}
+}
+S: {
+	A: {
+		a: 1
+	}
+	B: A & {
+		b: 2
+	}
+}
+-- out/export --
+T: {
+	A: {
+		a: 1
+		c: 3
+	}
+	B: {
+		a: 1
+		b: 2
+		c: 3
+		d: 4
+	}
+}
+S: {
+	A: {
+		a: 1
+	}
+	B: {
+		a: 1
+		b: 2
+	}
+}
+-- out/yaml --
+T:
+  A:
+    a: 1
+    c: 3
+  B:
+    a: 1
+    b: 2
+    c: 3
+    d: 4
+S:
+  A:
+    a: 1
+  B:
+    a: 1
+    b: 2
+-- out/json --
+{"T":{"A":{"a":1,"c":3},"B":{"a":1,"b":2,"c":3,"d":4}},"S":{"A":{"a":1},"B":{"a":1,"b":2}}}
+-- out/legacy-debug --
+<0>{T: <1>{A: <2>{a: 1, c: 3}, B: <3>{a: 1, b: 2, c: 3, d: 4}}, S: <4>{A: <5>{a: 1}, B: <6>{a: 1, b: 2}}}
diff --git a/cue/testdata/resolve/044_field templates.txtar b/cue/testdata/resolve/044_field templates.txtar
new file mode 100644
index 0000000..f4e65d6
--- /dev/null
+++ b/cue/testdata/resolve/044_field templates.txtar
@@ -0,0 +1,96 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: field templates
+#evalPartial
+-- in.cue --
+a: {
+	{[name=_]: int}
+	k: 1
+}
+b: {
+	{[X=_]: {x: 0, y: *1 | int}}
+	v: {}
+	w: {x: 0}
+}
+b: {[y=_]: {}}
+c: {
+	{[Name=_]: {name: Name, y: 1}}
+	foo: {}
+	bar: _
+}
+-- out/def --
+a: {
+	{[name=string]: int}
+	k: 1
+}
+b: {
+	{[X=string]: {
+		x: 0, y: *1 | int
+	}}
+	v: {
+		x: 0
+		y: *1 | int
+	}
+	w: {
+		x: 0
+		y: *1 | int
+	}
+}
+c: {
+	{[Name=string]: {
+		y: 1, name: Name
+	}}
+	foo: {
+		y:    1
+		name: "foo"
+	}
+	bar: {
+		y:    1
+		name: "bar"
+	}
+}
+-- out/export --
+a: {
+	k: 1
+}
+b: {
+	v: {
+		x: 0
+		y: 1
+	}
+	w: {
+		x: 0
+		y: 1
+	}
+}
+c: {
+	foo: {
+		y:    1
+		name: "foo"
+	}
+	bar: {
+		y:    1
+		name: "bar"
+	}
+}
+-- out/yaml --
+a:
+  k: 1
+b:
+  v:
+    x: 0
+    y: 1
+  w:
+    x: 0
+    y: 1
+c:
+  foo:
+    y: 1
+    name: foo
+  bar:
+    y: 1
+    name: bar
+-- out/json --
+{"a":{"k":1},"b":{"v":{"x":0,"y":1},"w":{"x":0,"y":1}},"c":{"foo":{"y":1,"name":"foo"},"bar":{"y":1,"name":"bar"}}}
+-- out/legacy-debug --
+<0>{a: <1>{[]: <2>(name: string)->int, k: 1}, b: <3>{[]: <4>(X: string)->(<5>{x: 0, y: (*1 | int)} & <6>{}), v: <7>{x: 0, y: (*1 | int)}, w: <8>{x: 0, y: (*1 | int)}}, c: <9>{[]: <10>(Name: string)-><11>{y: 1, name: <10>.Name}, foo: <12>{y: 1, name: "foo"}, bar: <13>{y: 1, name: "bar"}}}
diff --git a/cue/testdata/resolve/045_range unification.txtar b/cue/testdata/resolve/045_range unification.txtar
new file mode 100644
index 0000000..054002d
--- /dev/null
+++ b/cue/testdata/resolve/045_range unification.txtar
@@ -0,0 +1,95 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: range unification
+#evalPartial
+-- in.cue --
+	// with concrete values
+a1: >=1 & <=5 & 3
+a2: >=1 & <=5 & 1
+a3: >=1 & <=5 & 5
+a4: >=1 & <=5 & 6
+a5: >=1 & <=5 & 0
+
+a6:  3 & >=1 & <=5
+a7:  1 & >=1 & <=5
+a8:  5 & >=1 & <=5
+a9:  6 & >=1 & <=5
+a10: 0 & >=1 & <=5
+
+// with ranges
+b1: >=1 & <=5 & >=1 & <=5
+b2: >=1 & <=5 & >=1 & <=1
+b3: >=1 & <=5 & >=5 & <=5
+b4: >=1 & <=5 & >=2 & <=3
+b5: >=1 & <=5 & >=3 & <=9
+b6: >=1 & <=5 & >=5 & <=9
+b7: >=1 & <=5 & >=6 & <=9
+
+b8:  >=1 & <=5 & >=1 & <=5
+b9:  >=1 & <=1 & >=1 & <=5
+b10: >=5 & <=5 & >=1 & <=5
+b11: >=2 & <=3 & >=1 & <=5
+b12: >=3 & <=9 & >=1 & <=5
+b13: >=5 & <=9 & >=1 & <=5
+b14: >=6 & <=9 & >=1 & <=5
+
+// ranges with more general types
+c1: int & >=1 & <=5
+c2: >=1 & <=5 & int
+c3: string & >=1 & <=5
+c4: >=1 & <=5 & string
+
+// other types
+s1: >="d" & <="z" & "e"
+s2: >="d" & <="z" & "ee"
+
+n1: number & >=1 & <=2
+n2: int & >=1.1 & <=1.3
+n3: >=1.0 & <=3.0 & 2
+n4: >=0.0 & <=0.1 & 0.09999
+n5: >=1 & <=5 & 2.5
+-- out/def --
+	// with concrete values
+a1:  3
+a2:  1
+a3:  5
+a4:  _|_ // invalid value 6 (out of bound <=5)
+a5:  _|_ // invalid value 0 (out of bound >=1)
+a6:  3
+a7:  1
+a8:  5
+a9:  _|_ // invalid value 6 (out of bound <=5)
+a10: _|_ // invalid value 0 (out of bound >=1)
+
+// with ranges
+b1:  >=1 & <=5
+b2:  1
+b3:  5
+b4:  >=2 & <=3
+b5:  >=3 & <=5
+b6:  5
+b7:  _|_ // conflicting bounds >=6 and <=5
+b8:  >=1 & <=5
+b9:  1
+b10: 5
+b11: >=2 & <=3
+b12: >=3 & <=5
+b13: 5
+b14: _|_ // conflicting bounds >=6 and <=5
+
+// ranges with more general types
+c1: uint & >=1 & <=5
+c2: uint & >=1 & <=5
+c3: _|_ // conflicting values string and >=1 (mismatched types string and number)
+c4: _|_ // conflicting values (>=1 & <=5) and string (mismatched types number and string)
+
+// other types
+s1: "e"
+s2: "ee"
+n1: >=1 & <=2
+n2: _|_ // conflicting bounds int & >=1.1 and <=1.3
+n3: 2
+n4: 0.09999
+n5: 2.5
+-- out/legacy-debug --
+<0>{a1: 3, a2: 1, a3: 5, a4: _|_((<=5 & 6):invalid value 6 (out of bound <=5)), a5: _|_((>=1 & 0):invalid value 0 (out of bound >=1)), a6: 3, a7: 1, a8: 5, a9: _|_((<=5 & 6):invalid value 6 (out of bound <=5)), a10: _|_((>=1 & 0):invalid value 0 (out of bound >=1)), b1: (>=1 & <=5), b2: 1, b3: 5, b4: (>=2 & <=3), b5: (>=3 & <=5), b6: 5, b7: _|_(conflicting bounds >=6 and <=5), b8: (>=1 & <=5), b9: 1, b10: 5, b11: (>=2 & <=3), b12: (>=3 & <=5), b13: 5, b14: _|_(conflicting bounds >=6 and <=5), c1: (int & >=1 & <=5), c2: (<=5 & int & >=1), c3: _|_((string & >=1):conflicting values string and >=1 (mismatched types string and number)), c4: _|_(((>=1 & <=5) & string):conflicting values (>=1 & <=5) and string (mismatched types number and string)), s1: "e", s2: "ee", n1: (>=1 & <=2), n2: _|_(conflicting bounds int & >=1.1 and <=1.3), n3: 2, n4: 0.09999, n5: 2.5}
diff --git a/cue/testdata/resolve/046_predefined ranges.txtar b/cue/testdata/resolve/046_predefined ranges.txtar
new file mode 100644
index 0000000..e50f77a
--- /dev/null
+++ b/cue/testdata/resolve/046_predefined ranges.txtar
@@ -0,0 +1,19 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: predefined ranges
+#evalPartial
+-- in.cue --
+k1: int8
+k1: 44
+
+k2: int64
+k2: -8_000_000_000
+
+e1: int16
+e1: 100_000
+-- out/def --
+k1: 44
+k2: -8000000000
+e1: _|_ // invalid value 100000 (out of bound int & <=32767)
+-- out/legacy-debug --
+<0>{k1: 44, k2: -8000000000, e1: _|_((int & <=32767 & 100000):invalid value 100000 (out of bound int & <=32767))}
diff --git a/cue/testdata/resolve/047_struct comprehensions.txtar b/cue/testdata/resolve/047_struct comprehensions.txtar
new file mode 100644
index 0000000..eab9516
--- /dev/null
+++ b/cue/testdata/resolve/047_struct comprehensions.txtar
@@ -0,0 +1,52 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: struct comprehensions
+#evalPartial
+-- in.cue --
+obj: foo: a: "bar"
+obj: [Name=string]: {
+	a: *"dummy" | string
+	if true {
+		sub: as: a
+	}
+}
+
+for k, v in {def :: 1, opt?: 2, _hid: 3, reg: 4} {
+	"\(k)": v
+}
+-- out/def --
+obj: {
+	{[Name=string]: {
+		a: *"dummy" | string, sub: {
+			as: a
+		}
+	}}
+	foo: {
+		a: "bar"
+		sub: {
+			as: "bar"
+		}
+	}
+}
+reg: 4
+-- out/export --
+obj: {
+	foo: {
+		a: "bar"
+		sub: {
+			as: "bar"
+		}
+	}
+}
+reg: 4
+-- out/yaml --
+obj:
+  foo:
+    a: bar
+    sub:
+      as: bar
+reg: 4
+-- out/json --
+{"obj":{"foo":{"a":"bar","sub":{"as":"bar"}}},"reg":4}
+-- out/legacy-debug --
+<0>{obj: <1>{[]: <2>(Name: string)-><3>{a: (*"dummy" | string) if true yield <4>{sub: <5>{as: <3>.a}}}, foo: <6>{a: "bar", sub: <7>{as: "bar"}}}, reg: 4}
diff --git a/cue/testdata/resolve/048_builtins.txtar b/cue/testdata/resolve/048_builtins.txtar
new file mode 100644
index 0000000..45da3b7
--- /dev/null
+++ b/cue/testdata/resolve/048_builtins.txtar
@@ -0,0 +1,46 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: builtins
+#evalPartial
+-- in.cue --
+a1: {
+	a: and([b, c])
+	b: =~"oo"
+	c: =~"fo"
+}
+a2: a1 & {a: "foo"}
+a3: a1 & {a: "bar"}
+
+o1: {
+	a: or([b, c])
+	b: string
+	c: "bar"
+}
+o2: o1 & {a: "foo"}
+o3: o1 & {a: "foo", b: "baz"}
+-- out/def --
+a1: {
+	a: =~"oo" & =~"fo"
+	b: =~"oo"
+	c: =~"fo"
+}
+a2: a1 & {
+	a: "foo"
+}
+a3: a1 & {
+	a: "bar"
+}
+o1: {
+	a: string
+	b: string
+	c: "bar"
+}
+o2: o1 & {
+	a: "foo"
+}
+o3: o1 & {
+	a: "foo"
+	b: "baz"
+}
+-- out/legacy-debug --
+<0>{a1: <1>{a: (=~"oo" & =~"fo"), b: =~"oo", c: =~"fo"}, a2: <2>{a: "foo", b: =~"oo", c: =~"fo"}, a3: <3>{a: _|_((=~"oo" & "bar"):invalid value "bar" (does not match =~"oo")), b: =~"oo", c: =~"fo"}, o1: <4>{a: string, b: string, c: "bar"}, o2: <5>{a: "foo", b: string, c: "bar"}, o3: <6>{a: _|_(("baz" & "foo"):empty disjunction: conflicting values "baz" and "foo";("bar" & "foo"):empty disjunction: conflicting values "bar" and "foo"), b: "baz", c: "bar"}}
diff --git a/cue/testdata/resolve/049_self-reference cycles conflicts with strings.txtar b/cue/testdata/resolve/049_self-reference cycles conflicts with strings.txtar
new file mode 100644
index 0000000..f430b79
--- /dev/null
+++ b/cue/testdata/resolve/049_self-reference cycles conflicts with strings.txtar
@@ -0,0 +1,17 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: self-reference cycles conflicts with strings
+#evalPartial
+-- in.cue --
+a: {
+	x: y + "?"
+	y: x + "!"
+}
+a: x: "hey"
+-- out/def --
+a: {
+	x: _|_ // conflicting values "hey!?" and "hey"
+	y: "hey!"
+}
+-- out/legacy-debug --
+<0>{a: <1>{x: _|_(("hey!?" & "hey"):conflicting values "hey!?" and "hey"), y: "hey!"}}
diff --git a/cue/testdata/resolve/050_resolved self-reference cycles with disjunctions.txtar b/cue/testdata/resolve/050_resolved self-reference cycles with disjunctions.txtar
new file mode 100644
index 0000000..da3224f
--- /dev/null
+++ b/cue/testdata/resolve/050_resolved self-reference cycles with disjunctions.txtar
@@ -0,0 +1,26 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: resolved self-reference cycles with disjunctions
+#evalPartial
+-- in.cue --
+a: b & {x: 1} | {y:     1} // {x:1,y:3,z:2} | {y:1}
+b: {x:     2} | c & {z: 2} // {x:2} | {x:1,y:3,z:2}
+c: a & {y: 3} | {z:     3} // {x:1,y:3,z:2} | {z:3}
+-- out/def --
+a: b & {
+	x: 1
+} | {
+	y: 1
+}
+b: {
+	x: 2
+} | c & {
+	z: 2
+}
+c: a & {
+	y: 3
+} | {
+	z: 3
+}
+-- out/legacy-debug --
+<0>{a: (<1>{x: 1, y: 3, z: 2} | <2>{y: 1}), b: (<3>{x: 2} | <4>{x: 1, y: 3, z: 2}), c: (<5>{x: 1, y: 3, z: 2} | <6>{z: 3})}
diff --git a/cue/testdata/resolve/051_resolved self-reference cycles with disjunction.txtar b/cue/testdata/resolve/051_resolved self-reference cycles with disjunction.txtar
new file mode 100644
index 0000000..143906b
--- /dev/null
+++ b/cue/testdata/resolve/051_resolved self-reference cycles with disjunction.txtar
@@ -0,0 +1,122 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: resolved self-reference cycles with disjunction
+#evalPartial
+-- in.cue --
+// The second disjunct in xa1 is not resolvable and can be
+// eliminated:
+//   xa4 & 9
+//   (xa2 + 2) & 9
+//   ((xa3 + 2) + 2) & 9
+//   (((6 & xa1-2) + 2) + 2) & 9
+//   ((6 + 2) + 2) & 9 // 6 == xa1-2
+//   10 & 9 => _|_
+// The remaining values resolve.
+xa1: (xa2 & 8) | (xa4 & 9)
+xa2: xa3 + 2
+xa3: 6 & xa1-2
+xa4: xa2 + 2
+
+// The second disjunct in xb4 can be eliminated as both disjuncts
+// of xb3 result in an incompatible sum when substituted.
+xb1: (xb2 & 8) | (xb4 & 9)
+xb2: xb3 + 2
+xb3: (6 & (xb1 - 2)) | (xb4 & 9)
+xb4: xb2 + 2
+
+// Another variant with more disjunctions. xc1 remains with two
+// possibilities. Technically, only the first value is valid.
+// However, to fully determine that, all options of the remaining
+// disjunction will have to be evaluated algebraically, which is
+// not done.
+xc1: xc2 & 8 | xc4 & 9 | xc5 & 9
+xc2: xc3 + 2
+xc3: 6 & xc1-2
+xc4: xc2 + 1
+xc5: xc2 + 2
+
+// The above is resolved by setting xd1 explicitly.
+xd1: xd2 & 8 | xd4 & 9 | xd5 & 9
+xd2: xd3 + 2
+xd3: 6 & xd1-2
+xd4: xd2 + 1
+xd5: xd2 + 2
+xd1: 8
+
+// The above is resolved by setting xd1 explicitly to the wrong
+// value, resulting in an error.
+xe1: xe2 & 8 | xe4 & 9 | xe5 & 9
+xe2: xe3 + 2
+xe3: 6 & xe1-2
+xe4: xe2 + 1
+xe5: xe2 + 2
+xe1: 9
+
+// Only one solution.
+xf1: xf2 & 8 | xf4 & 9
+xf2: xf3 + 2
+xf3: 6 & xf1-2 | xf4 & 9
+xf4: xf2 + 2
+
+z1: z2+1 | z3+5
+z2: z3 + 2
+z3: z1 - 3
+z3: 8
+-- out/def --
+// The second disjunct in xa1 is not resolvable and can be
+// eliminated:
+//   xa4 & 9
+//   (xa2 + 2) & 9
+//   ((xa3 + 2) + 2) & 9
+//   (((6 & xa1-2) + 2) + 2) & 9
+//   ((6 + 2) + 2) & 9 // 6 == xa1-2
+//   10 & 9 => _|_
+// The remaining values resolve.
+xa1: 8
+xa2: 8
+xa4: 10
+xa3: 6
+
+// The second disjunct in xb4 can be eliminated as both disjuncts
+// of xb3 result in an incompatible sum when substituted.
+xb1: 8
+xb2: 8
+xb4: 10
+xb3: 6
+
+// Another variant with more disjunctions. xc1 remains with two
+// possibilities. Technically, only the first value is valid.
+// However, to fully determine that, all options of the remaining
+// disjunction will have to be evaluated algebraically, which is
+// not done.
+xc1: xc2 & 8 | xc4 & 9 | xc5 & 9
+xc2: xc3 + 2
+xc4: xc2 + 1
+xc5: xc2 + 2
+xc3: 6 & xc1-2
+
+// The above is resolved by setting xd1 explicitly.
+xd1: 8
+xd2: 8
+xd4: 9
+xd5: 10
+xd3: 6
+
+// The above is resolved by setting xd1 explicitly to the wrong
+// value, resulting in an error.
+xe1: _|_ // conflicting values 6 and 7
+xe2: _|_ // conflicting values 6 and 7
+xe4: _|_ // conflicting values 6 and 7
+xe5: _|_ // conflicting values 6 and 7
+xe3: _|_ // conflicting values 6 and 7
+
+// Only one solution.
+xf1: 8
+xf2: 8
+xf4: 10
+xf3: 6
+z1:  z2+1 | z3+5
+z2:  z3 + 2
+z3:  z1-3 & 8
+-- out/legacy-debug --
+<0>{xa1: 8, xa2: 8, xa4: 10, xa3: 6, xb1: 8, xb2: 8, xb4: 10, xb3: 6, xc1: ((<1>.xc2 & 8) | (<1>.xc4 & 9) | (<1>.xc5 & 9)), xc2: (<1>.xc3 + 2), xc4: (<1>.xc2 + 1), xc5: (<1>.xc2 + 2), xc3: (6 & (<1>.xc1 - 2)), xd1: 8, xd2: 8, xd4: 9, xd5: 10, xd3: 6, xe1: _|_((6 & 7):conflicting values 6 and 7), xe2: _|_((6 & 7):conflicting values 6 and 7), xe4: _|_((6 & 7):conflicting values 6 and 7), xe5: _|_((6 & 7):conflicting values 6 and 7), xe3: _|_((6 & 7):conflicting values 6 and 7), xf1: 8, xf2: 8, xf4: 10, xf3: 6, z1: ((<1>.z2 + 1) | (<1>.z3 + 5)), z2: (<1>.z3 + 2), z3: ((<1>.z1 - 3) & 8)}
diff --git a/cue/testdata/resolve/052_resolved self-reference cycles with disjunction with defaults.txtar b/cue/testdata/resolve/052_resolved self-reference cycles with disjunction with defaults.txtar
new file mode 100644
index 0000000..4fcd4b2
--- /dev/null
+++ b/cue/testdata/resolve/052_resolved self-reference cycles with disjunction with defaults.txtar
@@ -0,0 +1,97 @@
+# DO NOT EDIT; generated by go run testdata/gen.go
+#
+#name: resolved self-reference cycles with disjunction with defaults
+#evalPartial
+-- in.cue --
+// The disjunction in xa could be resolved, but as disjunctions
+// are not resolved for expression, it remains unresolved.
+xa1: (xa2 & 8) | *(xa4 & 9)
+xa2: xa3 + 2
+xa3: 6 & xa1-2
+xa4: xa2 + 2
+
+// As xb3 is a disjunction, xb2 cannot be resolved and evaluating
+// the cycle completely is broken. However, it is not an error
+// as the user might still resolve the disjunction.
+xb1: *(xb2 & 8) | (xb4 & 9)
+xb2: xb3 + 2
+xb3: *(6 & (xb1 - 2)) | (xb4 & 9)
+xb4: xb2 + 2
+
+// Another variant with more disjunctions. xc1 remains with two
+// possibilities. Technically, only the first value is valid.
+// However, to fully determine that, all options of the remaining
+// disjunction will have to be evaluated algebraically, which is
+// not done.
+xc1: *(xc2 & 8) | (xc4 & 9) | (xc5 & 9)
+xc2: xc3 + 2
+xc3: 6 & xc1-2
+xc4: xc2 + 1
+xc5: xc2 + 2
+
+// The above is resolved by setting xd1 explicitly.
+xd1: *(xd2 & 8) | xd4 & 9 | xd5 & 9
+xd2: xd3 + 2
+xd3: 6 & xd1-2
+xd4: xd2 + 1
+xd5: xd2 + 2
+
+// The above is resolved by setting xd1 explicitly to the wrong
+// value, resulting in an error.
+xe1: *(xe2 & 8) | xe4 & 9 | xe5 & 9
+xe2: xe3 + 2
+xe3: 6 & xe1-2
+xe4: xe2 + 1
+xe5: xe2 + 2
+xe1: 9
+
+z1: *(z2 + 1) | z3+5
+z2: z3 + 2
+z3: z1 - 3
+z3: 8
+-- out/def --
+// The disjunction in xa could be resolved, but as disjunctions
+// are not resolved for expression, it remains unresolved.
+xa1: 8
+xa2: 8
+xa4: 10
+xa3: 6
+
+// As xb3 is a disjunction, xb2 cannot be resolved and evaluating
+// the cycle completely is broken. However, it is not an error
+// as the user might still resolve the disjunction.
+xb1: 8
+xb2: 8
+xb4: 10
+xb3: 6
+
+// Another variant with more disjunctions. xc1 remains with two
+// possibilities. Technically, only the first value is valid.
+// However, to fully determine that, all options of the remaining
+// disjunction will have to be evaluated algebraically, which is
+// not done.
+xc1: *8 | 9 | _|_ // conflicting values 10 and 9
+xc2: 8
+xc4: 9
+xc5: 10
+xc3: 6
+
+// The above is resolved by setting xd1 explicitly.
+xd1: *8 | 9 | _|_ // conflicting values 10 and 9
+xd2: 8
+xd4: 9
+xd5: 10
+xd3: 6
+
+// The above is resolved by setting xd1 explicitly to the wrong
+// value, resulting in an error.
+xe1: _|_ // conflicting values 6 and 7
+xe2: _|_ // conflicting values 6 and 7
+xe4: _|_ // conflicting values 6 and 7
+xe5: _|_ // conflicting values 6 and 7
+xe3: _|_ // conflicting values 6 and 7
+z1:  *11 | 13
+z2:  10
+z3:  8
+-- out/legacy-debug --
+<0>{xa1: 8, xa2: 8, xa4: 10, xa3: 6, xb1: 8, xb2: 8, xb4: 10, xb3: 6, xc1: (*8 | 9), xc2: 8, xc4: 9, xc5: 10, xc3: 6, xd1: (*8 | 9), xd2: 8, xd4: 9, xd5: 10, xd3: 6, xe1: _|_((6 & 7):conflicting values 6 and 7), xe2: _|_((6 & 7):conflicting values 6 and 7), xe4: _|_((6 & 7):conflicting values 6 and 7), xe5: _|_((6 & 7):conflicting values 6 and 7), xe3: _|_((6 & 7):conflicting values 6 and 7), z1: (*11 | 13), z2: 10, z3: 8}