internal/core/eval: fix Environment linkage for Disjunctions

The Vertex value for a disjunction is copied into another value
causing the Vertex links in the Environment to point to the wrong
node. This causes args to be missed when resolving.

Ideally the node should not be copied, but as we don't dereferenece,
the pointer value needs to be exactly what it is now.

A better solution perhaps would be to implement dereferencing.

Note that this bug is only exposed through API usage, as during normal
evaluation only DisjunctionExprs will be used in computation.

This will break OpenAPI if not done correctly.

Change-Id: I6a780dc11c7f44ca9a47c4838ea2502371bf7505
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6647
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/internal/core/eval/closed.go b/internal/core/eval/closed.go
index fcfa52a..0b8025e 100644
--- a/internal/core/eval/closed.go
+++ b/internal/core/eval/closed.go
@@ -289,6 +289,8 @@
 // "and" semantics of conjunctions. It generates an error if a field is not
 // allowed.
 func (n *acceptor) verifyArcAllowed(ctx *adt.OpContext, f adt.Feature) *adt.Bottom {
+	// TODO(perf): this will also generate a message for f == 0. Do something
+	// more clever and only generate this when it is a user error.
 	filter := f.IsString() || f == adt.InvalidLabel
 	if filter && !n.verifyArcRecursive(ctx, n.tree, f) {
 		label := f.SelectorString(ctx)
diff --git a/internal/core/eval/eval.go b/internal/core/eval/eval.go
index 2121e42..82dba9a 100644
--- a/internal/core/eval/eval.go
+++ b/internal/core/eval/eval.go
@@ -153,6 +153,15 @@
 			// information than incorrect information.
 			for _, d := range d.Values {
 				d.Conjuncts = nil
+				for _, a := range d.Arcs {
+					for _, x := range a.Conjuncts {
+						// All the environments for embedded structs need to be
+						// dereferenced.
+						for env := x.Env; env != nil && env.Vertex == v; env = env.Up {
+							env.Vertex = d
+						}
+					}
+				}
 			}
 		}
 
@@ -251,13 +260,28 @@
 
 	case d != nil && len(d.Values) > 0:
 		v.Value = d
-		v.Arcs = nil
-		v.Structs = nil
 		// The conjuncts will have too much information. Better have no
 		// information than incorrect information.
 		for _, d := range d.Values {
+			// We clear the conjuncts for now. As these disjuncts are for API
+			// use only, we will fill them out when necessary (using Defaults).
 			d.Conjuncts = nil
+
+			// TODO: use a more principled form of dereferencing. For instance,
+			// disjuncts could already be assumed to be the given Vertex, and
+			// the the main vertex could be dereferenced during evaluation.
+			for _, a := range d.Arcs {
+				for _, x := range a.Conjuncts {
+					// All the environments for embedded structs need to be
+					// dereferenced.
+					for env := x.Env; env != nil && env.Vertex == v; env = env.Up {
+						env.Vertex = d
+					}
+				}
+			}
 		}
+		v.Arcs = nil
+		// v.Structs = nil // TODO: should we keep or discard the Structs?
 
 	default:
 		if r := n.result(); r.Value != nil {