cue: allow bottom for optional fields

Note ¬P's relation to  P → ⊥.
This is especially important to get right
for closed structs. It does not have much
impact now.

Also fixes a few minor other things:
- improved error message
- don't use helpers for testing (t.Run gives
  context and it is more useful to have
  the failure location in the test code).

Change-Id: Id88af58b8f882fc0e4dc9cda1c0a9098d4a82344
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2862
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/kind.go b/cue/kind.go
index cae1ea0..1eec58a 100644
--- a/cue/kind.go
+++ b/cue/kind.go
@@ -303,7 +303,8 @@
 	default:
 		panic("unimplemented")
 	}
+	// TODO: localize
 	msg = "invalid operation %[2]s %[1]s %[3]s"
-	msg += fmt.Sprintf(" (operator not defined on %s)", valBits)
+	msg += fmt.Sprintf(" (operator '%s' not defined on %s)", op, valBits)
 	return bottomKind, false, msg
 }
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index dbbd01f..9a07c9c 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -28,7 +28,6 @@
 }
 
 func compileFile(t *testing.T, body string) (*context, *structLit) {
-	t.Helper()
 	ctx, inst, errs := compileInstance(t, body)
 	if errs != nil {
 		t.Fatal(errs)
@@ -37,8 +36,6 @@
 }
 
 func compileInstance(t *testing.T, body string) (*context, *Instance, error) {
-	t.Helper()
-
 	var r Runtime
 	inst, err := r.Parse("test", body)
 
@@ -52,10 +49,8 @@
 }
 
 func rewriteHelper(t *testing.T, cases []testCase, r rewriteMode) {
-	t.Helper()
 	for _, tc := range cases {
 		t.Run(tc.desc, func(t *testing.T) {
-			t.Helper()
 			ctx, obj := compileFile(t, tc.in)
 			ctx.trace = *traceOn
 			root := testResolve(ctx, obj, r)
diff --git a/cue/validate.go b/cue/validate.go
index 5cdbce4..02a4984 100644
--- a/cue/validate.go
+++ b/cue/validate.go
@@ -26,7 +26,10 @@
 		if ctx.maxDepth++; ctx.maxDepth > 20 {
 			return nil
 		}
-		for i := range x.arcs {
+		for i, a := range x.arcs {
+			if a.optional {
+				continue
+			}
 			if err := validate(ctx, x.at(ctx, i)); err != nil {
 				ctx.maxDepth--
 				return err