cue: for structs, iterate only on non-optional regular fields

Change-Id: If516e96e68b135972942b9f5cfdfb49df3231297
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3187
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index b1c776c..4697e85 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -1580,8 +1580,12 @@
 					sub as: a
 				}
 			}
+
+			for k, v in { def :: 1, opt?: 2, _hid: 3, reg: 4 } {
+				"\(k)": v
+			}
 		`,
-		out: `<0>{obj: <1>{<>: <2>(Name: string)-><3>{a: (*"dummy" | string) if true yield <4>{sub: <5>{as: <3>.a}}}, foo: <6>{a: "bar", sub: <7>{as: "bar"}}}}`,
+		out: `<0>{obj: <1>{<>: <2>(Name: string)-><3>{a: (*"dummy" | string) if true yield <4>{sub: <5>{as: <3>.a}}}, foo: <6>{a: "bar", sub: <7>{as: "bar"}}}, reg: 4}`,
 	}, {
 		desc: "builtins",
 		in: `
diff --git a/cue/value.go b/cue/value.go
index 6f5f659..14b380e 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -1455,6 +1455,9 @@
 				ctx.labelStr(a.feature),
 				nil,
 			}
+			if a.definition || a.optional || a.feature&hidden != 0 {
+				continue
+			}
 			val := src.at(ctx, i)
 			v := fn.call(ctx, x, key, val)
 			if err, ok := v.(*bottom); ok {
diff --git a/doc/ref/spec.md b/doc/ref/spec.md
index 088436d..3569fa8 100644
--- a/doc/ref/spec.md
+++ b/doc/ref/spec.md
@@ -1239,8 +1239,7 @@
 
 A _closed struct_ `c` is a struct whose instances may not have regular fields
 not defined in `c`.
-For the purpose of unification,
-closing a struct is equivalent to adding an optional field with value `_|_`
+Closing a struct is equivalent to adding an optional field with value `_|_`
 for all undefined fields.
 
 Syntactically, closed structs can be explicitly created with the `close` builtin
@@ -2570,11 +2569,14 @@
 The `for` clause binds the defined identifiers, on each iteration, to the next
 value of some iterable value in a new scope.
 A `for` clause may bind one or two identifiers.
-If there is one identifier, it binds it to the value, for instance
-a list element, a struct field value or a range element.
+If there is one identifier, it binds it to the value of
+a list element or struct field value.
 If there are two identifiers, the first value will be the key or index,
 if available, and the second will be the value.
 
+For lists, `for` iterates over all elements in the list after closing it.
+For structs, `for` iterates over all non-optional regular fields.
+
 An `if` clause, or guard, specifies an expression that terminates the current
 iteration if it evaluates to false.