cue: retain default bottom

This bug was a left-over from the old
defaults semantics.

Change-Id: I3b4d38fd41ea02f36fac3be69862910d5e5d9851
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2176
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/cue/export.go b/cue/export.go
index 343edcc..1382ad8 100644
--- a/cue/export.go
+++ b/cue/export.go
@@ -568,12 +568,14 @@
 
 	case *bottom:
 		err := &ast.BottomLit{}
-		comment := &ast.Comment{Text: "/* " + x.msg + " */"}
-		err.AddComment(&ast.CommentGroup{
-			Line:     true,
-			Position: 1,
-			List:     []*ast.Comment{comment},
-		})
+		if x.msg != "" {
+			comment := &ast.Comment{Text: "/* " + x.msg + " */"}
+			err.AddComment(&ast.CommentGroup{
+				Line:     true,
+				Position: 1,
+				List:     []*ast.Comment{comment},
+			})
+		}
 		return err
 
 	case *top:
diff --git a/cue/export_test.go b/cue/export_test.go
index 464c56f..dd4c8cd 100644
--- a/cue/export_test.go
+++ b/cue/export_test.go
@@ -161,8 +161,8 @@
 			}`,
 		out: unindent(`
 			{
-				a: 1 | 2
-				b: [1 | 2]
+				a: 1 | 2 | *_|_
+				b: [1 | 2 | *_|_]
 			}`),
 	}, {
 		raw:  true,
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index 605b486..bd1aebe 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -425,7 +425,7 @@
 			// All errors are treated the same as per the unification model.
 			i1: [1, 2][3] | "c"
 			`,
-		out: `<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"}`,
+		out: `<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"}`,
 	}, {
 		desc: "types",
 		in: `
@@ -547,7 +547,7 @@
 			b: *"b" | "a"
 			c: a & b
 			`,
-		out: `<0>{a: "a", b: "b", c: _|_(("a" | "b"):more than one element remaining ("a" and "b"))}`,
+		out: `<0>{a: "a", b: "b", c: _|_(("a" | "b" | *_|_):more than one element remaining ("a" and "b"))}`,
 	}, {
 		desc: "associativity of defaults",
 		in: `
@@ -1929,10 +1929,10 @@
 			`a1: _|_(((*0 | 1) & (<5>.a3 - <5>.a2)):cycle detected), ` +
 			`a3: 1, ` +
 			`a2: _|_(((*0 | 1) & (<5>.a3 - <5>.a1)):cycle detected), ` +
-			`b1: _|_((0 | 1):more than one element remaining (0 and 1)), ` +
-			`b2: _|_((0 | 1):more than one element remaining (0 and 1)), ` +
-			`c1: _|_((<0>{a: 1, b: 2} | <1>{a: 2, b: 1}):more than one element remaining (<0>{a: 1, b: 2} and <1>{a: 2, b: 1})), ` +
-			`c2: _|_((<2>{a: 2, b: 1} | <3>{a: 1, b: 2}):more than one element remaining (<2>{a: 2, b: 1} and <3>{a: 1, b: 2}))}`,
+			`b1: _|_((0 | 1 | *_|_):more than one element remaining (0 and 1)), ` +
+			`b2: _|_((0 | 1 | *_|_):more than one element remaining (0 and 1)), ` +
+			`c1: _|_((<0>{a: 1, b: 2} | <1>{a: 2, b: 1} | *_|_):more than one element remaining (<0>{a: 1, b: 2} and <1>{a: 2, b: 1})), ` +
+			`c2: _|_((<2>{a: 2, b: 1} | <3>{a: 1, b: 2} | *_|_):more than one element remaining (<2>{a: 2, b: 1} and <3>{a: 1, b: 2}))}`,
 	}}
 	rewriteHelper(t, testCases, evalFull)
 }
diff --git a/cue/value.go b/cue/value.go
index f862ca1..66ae5e4 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -1195,6 +1195,8 @@
 	// when the result of this value is unified with another value.
 	noManifest := ctx.noManifest
 	ctx.noManifest = true
+	hasMarked := false
+	var markedErr *bottom
 outer:
 	for i, v := range x.values {
 		// TODO: this is pre-evaluation is quite aggressive. Verify whether
@@ -1203,8 +1205,14 @@
 		// defaults. The drawback of this approach is that printed intermediate
 		// results will not look great.
 		if err := validate(ctx, v.val); err != nil {
+			if v.marked {
+				markedErr = err
+			}
 			continue
 		}
+		if v.marked {
+			hasMarked = true
+		}
 		for j, w := range x.values {
 			if i == j {
 				continue
@@ -1225,6 +1233,10 @@
 		x.values[k] = v
 		k++
 	}
+	if !hasMarked && markedErr != nil && (k > 1 || !x.values[0].val.kind().isGround()) {
+		x.values[k] = dValue{&bottom{}, true}
+		k++
+	}
 	ctx.noManifest = noManifest
 
 	switch k {