internal/core/adt: finalize comprehension arcs

Arcs need to be evaluated before used.
It often doesn't matter, which is why this wasn't caught before.

Change-Id: Ia9fb33666f6ee3dd60929ed9a01fb42f38da02fa
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6651
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/testdata/comprehensions/nested.txtar b/cue/testdata/comprehensions/nested.txtar
new file mode 100644
index 0000000..459a554
--- /dev/null
+++ b/cue/testdata/comprehensions/nested.txtar
@@ -0,0 +1,223 @@
+-- in.cue --
+package kube
+service: "node-exporter": {
+	spec: {
+		ports: [{
+			name:     "metrics"
+			port:     9100
+			protocol: "TCP"
+		}]
+	}
+}
+deployment: "node-exporter": {
+	spec: template: {
+		spec: {
+			containers: [{
+				ports: [{
+					containerPort: 9100
+					name:          "scrape"
+				}]
+			}]
+		}
+	}
+}
+service: [ID=string]: {
+	spec: {
+		ports: [...{
+			port:     int
+			protocol: *"TCP" | "UDP"
+			name:     string | *"client"
+		}]
+	}
+}
+deployment: [ID=string]: { }
+deployment: [ID=_]: _spec & {}
+_spec: {
+	_name: string
+	spec: template: {
+		spec: containers: [{name: _name}]
+	}
+}
+_spec: spec: template: spec: containers: [...{
+	ports: [...{
+		_export: *true | false // include the port in the service
+	}]
+}]
+for k, v in deployment {
+	service: "\(k)": {
+		spec: selector: v.spec.template.metadata.labels
+		spec: ports: [
+			for c in v.spec.template.spec.containers
+			for p in c.ports
+			if p._export {
+				let Port = p.containerPort // Port is an alias
+				port:       *Port | int
+				targetPort: *Port | int
+			},
+		]
+	}
+}
+-- out/eval --
+(struct){
+  service: (struct){
+    "node-exporter": (struct){
+      spec: (struct){
+        ports: (#list){
+          0: (struct){
+            name: (string){ "metrics" }
+            port: (int){ 9100 }
+            protocol: (string){ "TCP" }
+            targetPort: (int){ |(*(int){ 9100 }, (int){ int }) }
+          }
+        }
+        selector: (_|_){
+          // [incomplete] service."node-exporter".spec.selector: undefined field metadata:
+          //     ./in.cue:47:35
+        }
+      }
+    }
+  }
+  deployment: (struct){
+    "node-exporter": (struct){
+      spec: (struct){
+        template: (struct){
+          spec: (struct){
+            containers: (#list){
+              0: (struct){
+                ports: (#list){
+                  0: (struct){
+                    containerPort: (int){ 9100 }
+                    name: (string){ "scrape" }
+                    _export: (bool){ |(*(bool){ true }, (bool){ false }) }
+                  }
+                }
+                name: (string){ string }
+              }
+            }
+          }
+        }
+      }
+      _name: (string){ string }
+    }
+  }
+  _spec: (struct){
+    _name: (string){ string }
+    spec: (struct){
+      template: (struct){
+        spec: (struct){
+          containers: (#list){
+            0: (struct){
+              name: (string){ string }
+              ports: (list){
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+-- out/compile --
+--- in.cue
+{
+  service: {
+    "node-exporter": {
+      spec: {
+        ports: [
+          {
+            name: "metrics"
+            port: 9100
+            protocol: "TCP"
+          },
+        ]
+      }
+    }
+  }
+  deployment: {
+    "node-exporter": {
+      spec: {
+        template: {
+          spec: {
+            containers: [
+              {
+                ports: [
+                  {
+                    containerPort: 9100
+                    name: "scrape"
+                  },
+                ]
+              },
+            ]
+          }
+        }
+      }
+    }
+  }
+  service: {
+    [string]: {
+      spec: {
+        ports: [
+          ...{
+            port: int
+            protocol: (*"TCP"|"UDP")
+            name: (string|*"client")
+          },
+        ]
+      }
+    }
+  }
+  deployment: {
+    [string]: {}
+  }
+  deployment: {
+    [_]: (〈1;_spec〉 & {})
+  }
+  _spec: {
+    _name: string
+    spec: {
+      template: {
+        spec: {
+          containers: [
+            {
+              name: 〈4;_name〉
+            },
+          ]
+        }
+      }
+    }
+  }
+  _spec: {
+    spec: {
+      template: {
+        spec: {
+          containers: [
+            ...{
+              ports: [
+                ...{
+                  _export: (*true|false)
+                },
+              ]
+            },
+          ]
+        }
+      }
+    }
+  }
+  for k, v in 〈0;deployment〉 {
+    service: {
+      "\(〈2;k〉)": {
+        spec: {
+          selector: 〈4;v〉.spec.template.metadata.labels
+        }
+        spec: {
+          ports: [
+            for _, c in 〈4;v〉.spec.template.spec.containers for _, p in 〈0;c〉.ports if 〈0;p〉._export {
+              port: (*〈0;let Port〉|int)
+              targetPort: (*〈0;let Port〉|int)
+            },
+          ]
+        }
+      }
+    }
+  }
+}
diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go
index 4836405..4bedc1e 100644
--- a/internal/core/adt/expr.go
+++ b/internal/core/adt/expr.go
@@ -1154,13 +1154,18 @@
 			continue
 		}
 
-		n := &Vertex{Arcs: []*Vertex{
-			{Label: x.Value, Conjuncts: a.Conjuncts}, // TODO: only needed if value label != _
-		}}
+		n := &Vertex{status: Finalized}
+
+		// TODO: only needed if value label != _
+		b := *a
+		b.Label = x.Value
+		n.Arcs = append(n.Arcs, &b)
+
 		if x.Key != 0 {
 			v := &Vertex{Label: x.Key}
 			key := a.Label.ToValue(c)
 			v.AddConjunct(MakeConjunct(c.Env(0), key))
+			v.SetValue(c, Finalized, key)
 			n.Arcs = append(n.Arcs, v)
 		}