cue: exclude definitions from value lookup

Change-Id: I007211d38db5ad08b2fb21aad66f46c850f5cd08
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3322
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/eval.go b/cue/eval.go
index ee66cba..9874a9b 100644
--- a/cue/eval.go
+++ b/cue/eval.go
@@ -101,6 +101,10 @@
 			s := index.strValue()
 			// TODO: must lookup
 			n := v.lookup(ctx, ctx.strLabel(s))
+			if n.definition {
+				return ctx.mkErr(x, index,
+					"field %q is a definition", s)
+			}
 			if n.optional {
 				return ctx.mkErr(x, index, codeIncomplete, "field %q is optional", s)
 			}
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index 6239022..98e505f 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -839,8 +839,13 @@
 			e4: [1,2,3][3]
 			e5: [1,2,3][-1]
 			e6: (*[]|{})[1]
+			def: {
+				a: 1
+				b :: 3
+			}
+			e7: def["b"]
 		`,
-		out: `<0>{a: 2, b: "bar", c: _|_("3":invalid list index "3" (type string)), l: [], d: _|_([]:index 0 out of bounds), e1: _|_("":invalid list index "" (type string)), e2: _|_(2:invalid operation: 2[2] (type int does not support indexing)), e3: _|_(true:invalid list index true (type bool)), e4: _|_([1,2,3]:index 3 out of bounds), e5: _|_(-1:invalid list index -1 (index must be non-negative)), e6: _|_([]:index 1 out of bounds)}`,
+		out: `<0>{a: 2, b: "bar", c: _|_("3":invalid list index "3" (type string)), l: [], d: _|_([]:index 0 out of bounds), e1: _|_("":invalid list index "" (type string)), e2: _|_(2:invalid operation: 2[2] (type int does not support indexing)), e3: _|_(true:invalid list index true (type bool)), e4: _|_([1,2,3]:index 3 out of bounds), e5: _|_(-1:invalid list index -1 (index must be non-negative)), e6: _|_([]:index 1 out of bounds), def: <1>{a: 1, b :: 3}, e7: _|_(<2>.def["b"]:field "b" is a definition)}`,
 		// }, {
 		// NOTE: string indexing no longer supported.
 		// Keeping it around until this is no longer an experiment.
@@ -1599,7 +1604,7 @@
 		out: `<0>{k1: 44, k2: -8000000000, ` +
 			`e1: _|_((int & <=32767 & 100000):invalid value 100000 (out of bound int & <=32767))}`,
 	}, {
-		desc: "field comprehensions",
+		desc: "struct comprehensions",
 		in: `
 			obj foo a: "bar"
 			obj <Name>: {
diff --git a/doc/ref/spec.md b/doc/ref/spec.md
index 0f6744d..11dbb14 100644
--- a/doc/ref/spec.md
+++ b/doc/ref/spec.md
@@ -1986,7 +1986,8 @@
 for `a` of struct type:
 
 - the index `x` unified with `string` must be concrete.
-- the value of the field named `x` of struct `a`, if this field exists
+- the value of the regular and non-optional field named `x` of struct `a`,
+  if this field exists
 - bottom (an error), otherwise