cue: prioritize missing field over incomplete errors

Fixes #315
Fixes #318

Change-Id: Ieaabb51513b5cb3923576a645120a39dec6b5dee
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5324
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/testdata/script/issue315.txt b/cmd/cue/cmd/testdata/script/issue315.txt
new file mode 100644
index 0000000..8d3cd83
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/issue315.txt
@@ -0,0 +1,27 @@
+! cue vet -c file.cue
+
+cmp stderr expect-stderr
+
+-- expect-stderr --
+incomplete value X.y in interpolation:
+    ./file.cue:16:3
+    ./file.cue:3:5
+-- file.cue --
+X :: {
+	x: string
+	y: string
+	z: string
+}
+
+X :: {
+	x: "x"
+	z: "z"
+}
+
+"""
+hello
+world
+\(X.x)
+\(X.y)
+\(X.z)
+"""
diff --git a/cue/eval.go b/cue/eval.go
index 41bd0ce..000ebea 100644
--- a/cue/eval.go
+++ b/cue/eval.go
@@ -380,6 +380,7 @@
 		defer func() { ctx.debugPrint("result:", result) }()
 	}
 	buf := bytes.Buffer{}
+	var incomplete value
 	for _, v := range x.parts {
 		switch e := ctx.manifest(v).(type) {
 		case *bottom:
@@ -392,10 +393,14 @@
 				return ctx.mkErr(e, "expression in interpolation must evaluate to a number kind or string (found %v)", k)
 			}
 			if !k.isGround() {
-				return ctx.mkErr(e, codeIncomplete, "incomplete")
+				incomplete = v
 			}
 		}
 	}
+	if incomplete != nil {
+		return ctx.mkErr(incomplete, codeIncomplete,
+			"incomplete value %s in interpolation", ctx.str(incomplete))
+	}
 	return &stringLit{x.baseValue, buf.String(), nil}
 }
 
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index ccbd647..2e21e1b 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -2962,6 +2962,24 @@
 		for x in [1] { y }
 		`,
 		out: `<0>{y: 1, a: 2}`,
+	}, {
+		desc: "issue318",
+		in: `
+		T :: {
+			arg: x: string
+			out1: "\(arg.x) \(arg.y)"
+			out2: "\(arg.y)"
+			vx: arg.x
+			vy: arg.y
+		}
+		`,
+		out: `<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")}}`,
 	}}
 	rewriteHelper(t, testCases, evalFull)
 }