cue: preserve path info in unification errors

We can do so by using Validate instead of the
validate used for disjunctions.

Change-Id: I96803f22263890ddec6694ffa278fdf19177d37e
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2561
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/testdata/tasks/cmd_baddisplay.out b/cmd/cue/cmd/testdata/tasks/cmd_baddisplay.out
index 39304d4..fa756db 100644
--- a/cmd/cue/cmd/testdata/tasks/cmd_baddisplay.out
+++ b/cmd/cue/cmd/testdata/tasks/cmd_baddisplay.out
@@ -1,3 +1,3 @@
-unsupported op &(int, string):
+text:unsupported op &(int, string):
     ./testdata/tasks/task_tool.cue:29:9
     tool/cli:4:9
diff --git a/cue/errors.go b/cue/errors.go
index 8fce493..3bfa563 100644
--- a/cue/errors.go
+++ b/cue/errors.go
@@ -82,6 +82,9 @@
 }
 
 func (e *valueError) Path() (a []string) {
+	if e.v.path == nil {
+		return nil
+	}
 	a, _ = e.v.path.appendPath(a, e.v.idx)
 	return a
 }
diff --git a/cue/types.go b/cue/types.go
index 38e6a70..be07f26 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -1147,10 +1147,21 @@
 	b := w.path.v
 	src := binSrc(token.NoPos, opUnify, a, b)
 	val := mkBin(ctx, src.Pos(), opUnify, a, b)
-	if err := validate(ctx, val.evalPartial(ctx)); err != nil {
-		val = err
+	u := newValueRoot(ctx, val)
+	if err := u.Validate(); err != nil {
+		// TODO: record all errors in a Value.
+		switch x := errors.Errors(err)[0].(type) {
+		case *valueError:
+			p := *x.v.path
+			p.v = x.err
+			p.cache = x.err
+			u = Value{x.v.idx, &p}
+
+		default:
+			u = newValueRoot(ctx, ctx.mkErr(src, err))
+		}
 	}
-	return newValueRoot(ctx, val)
+	return u
 }
 
 // Format prints a debug version of a value.