cue: support multierror return from Unify

Also fixes:
- file naming issue in Marshalling, which was not
  relative to the module root, if available.
- gocode generated output was not checked
  against golden (which was only used in gen_test.go)

Change-Id: I6a5f5363e2d0656ef3935fc46f84444ccbdd9a3e
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2942
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/builtin.go b/cue/builtin.go
index c6fc328..f7dbefa 100644
--- a/cue/builtin.go
+++ b/cue/builtin.go
@@ -359,10 +359,7 @@
 }
 
 func (c *callCtxt) errf(src source, underlying error, format string, args ...interface{}) {
-	a := make([]interface{}, 0, 2+len(args))
-	if underlying != nil {
-		a = append(a, underlying)
-	}
+	a := make([]interface{}, 0, 1+len(args))
 	a = append(a, format)
 	a = append(a, args...)
 	err := c.ctx.mkErr(src, a...)
diff --git a/cue/errors.go b/cue/errors.go
index b8f8436..5335733 100644
--- a/cue/errors.go
+++ b/cue/errors.go
@@ -51,6 +51,9 @@
 }
 
 func (v Value) toErr(b *bottom) errors.Error {
+	if b.err != nil {
+		return b.err
+	}
 	return &valueError{
 		v:   v,
 		err: b,
@@ -127,12 +130,9 @@
 	format    string
 	args      []interface{}
 
-	// Debugging info
+	err     errors.Error // pass-through from higher-level API
 	value   value
 	wrapped *bottom
-
-	// TODO: file at which the error was generated in the code.
-	// File positions of where the error occurred.
 }
 
 func (x *bottom) kind() kind { return bottomKind }
@@ -209,6 +209,8 @@
 			e.code = x
 		case *bottom:
 			e.wrapped = x
+		case errors.Error:
+			e.err = x
 		case value:
 		case string:
 			e.format = x
diff --git a/cue/lit.go b/cue/lit.go
index 5fecf92..6252781 100644
--- a/cue/lit.go
+++ b/cue/lit.go
@@ -181,7 +181,7 @@
 	src := newExpr(node)
 	str, err := q.Unquote(s)
 	if err != nil {
-		return ctx.mkErr(src, err, "invalid string: %v", err)
+		return ctx.mkErr(src, "invalid string: %v", err)
 	}
 	if q.IsDouble() {
 		return &stringLit{src, str, nil}
diff --git a/cue/marshal.go b/cue/marshal.go
index 0feb4dd..843f018 100644
--- a/cue/marshal.go
+++ b/cue/marshal.go
@@ -159,8 +159,13 @@
 		filename := "unmarshal"
 		if i.inst != nil && len(i.inst.Files) == 1 {
 			filename = i.inst.Files[0].Filename
-			if i.Dir != "" {
-				filename, _ = filepath.Rel(i.Dir, filename)
+
+			dir := i.Dir
+			if i.inst != nil && i.inst.Root != "" {
+				dir = i.inst.Root
+			}
+			if dir != "" {
+				filename, _ = filepath.Rel(dir, filename)
 			}
 		}
 
diff --git a/cue/types.go b/cue/types.go
index c656759..c31a2d2 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -1242,17 +1242,7 @@
 	val := mkBin(ctx, src.Pos(), opUnify, a, b)
 	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))
-		}
+		u = newValueRoot(ctx, ctx.mkErr(src, err))
 	}
 	return u
 }
diff --git a/encoding/gocode/gen_test.go b/encoding/gocode/gen_test.go
index 6f01c2b..d1bb8c2 100644
--- a/encoding/gocode/gen_test.go
+++ b/encoding/gocode/gen_test.go
@@ -42,7 +42,7 @@
 			v := &pkg1.OtherStruct{A: "car"}
 			return v.Validate()
 		}(),
-		want: "A: invalid value \"car\" (does not satisfy strings.ContainsAny(\"X\")):\n    pkg1/instance.cue:x:x",
+		want: "A: invalid value \"car\" (does not satisfy strings.ContainsAny(\"X\")):\n    pkg1/instance.cue:x:x\nP: invalid value 0 (out of bound >5):\n    pkg2/instance.cue:x:x",
 	}, {
 		name: "failing field of type int",
 		got: func() error {
@@ -53,7 +53,7 @@
 	}, {
 		name: "failing nested struct ",
 		got: func() error {
-			v := &pkg1.MyStruct{A: 5, B: "dog", O: &pkg1.OtherStruct{A: "car"}}
+			v := &pkg1.MyStruct{A: 5, B: "dog", O: &pkg1.OtherStruct{A: "car", P: 6}}
 			return v.Validate()
 		}(),
 		want: "O.A: invalid value \"car\" (does not satisfy strings.ContainsAny(\"X\")):\n    pkg1/instance.cue:x:x",
diff --git a/encoding/gocode/generator_test.go b/encoding/gocode/generator_test.go
index 70e0aa8..a4ad90a 100644
--- a/encoding/gocode/generator_test.go
+++ b/encoding/gocode/generator_test.go
@@ -26,6 +26,7 @@
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/load"
+	"github.com/kylelemons/godebug/diff"
 )
 
 var update = flag.Bool("update", false, "update test files")
@@ -62,13 +63,21 @@
 			if err != nil {
 				t.Fatal(errStr(err))
 			}
-			// t.Log(string(b))
 
 			goFile := filepath.Join("testdata", d.Name(), "cue_gen.go")
 			if *update {
 				_ = ioutil.WriteFile(goFile, b, 0644)
 				return
 			}
+
+			want, err := ioutil.ReadFile(goFile)
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			if d := diff.Diff(string(want), string(b)); d != "" {
+				t.Errorf("files differ:\n%v", d)
+			}
 		})
 	}
 }