cue: make defaults associative

Change-Id: Iad95267e29f08d595b4acbf151fbbe5ccbfb0233
diff --git a/cue/eval.go b/cue/eval.go
index e3ca92d..fa204a8 100644
--- a/cue/eval.go
+++ b/cue/eval.go
@@ -313,7 +313,16 @@
 	for _, v := range x.values {
 		n := v.val.evalPartial(ctx)
 		changed = changed || n != v.val
-		dn.add(ctx, n, v.marked)
+		// Including elements of disjunctions recursively makes default handling
+		// associative (*a | (*b|c)) == ((*a|*b) | c).
+		if d, ok := n.(*disjunction); ok {
+			changed = true
+			for _, dv := range d.values {
+				dn.add(ctx, dv.val, dv.marked)
+			}
+		} else {
+			dn.add(ctx, n, v.marked)
+		}
 	}
 	// TODO: move to evaluator
 	if !changed {
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index 6c9032c..47cd3fc 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -400,13 +400,15 @@
 			`,
 		out: `<0>{a: "a", b: "b", c: _|_((*"a" | *"b"):more than one default remaining ("a" and "b"))}`,
 	}, {
-		desc: "disambiguation non-conflict",
+		desc: "associativity of defaults",
 		in: `
 			a: *"a" | ("b" | "c")
 			b: (*"a" | "b") | "c"
-			c: a & b
+			c: *"a" | (*"b" | "c")
+			x: a & b
+			y: b & c
 			`,
-		out: `<0>{a: "a", b: _|_(((*"a" | "b") | "c"):more than one element remaining ((*"a" | "b") and "c")), c: "a"}`,
+		out: `<0>{a: "a", b: "a", c: _|_((*"a" | *"b" | "c"):more than one default remaining ("a" and "b")), x: "a", y: _|_((*"a" | *"b" | "c"):more than one default remaining ("a" and "b"))}`,
 	}}
 	rewriteHelper(t, testCases, evalFull)
 }
diff --git a/doc/ref/spec.md b/doc/ref/spec.md
index 7e0691c..deabfbc 100644
--- a/doc/ref/spec.md
+++ b/doc/ref/spec.md
@@ -602,10 +602,6 @@
 A _disjunction_ of two values `a` and `b`, denoted as `a | b` in CUE,
 defines the smallest value `d` such that `a ⊑ d` and `b ⊑ d`.
 This style of disjunctions is sometimes also referred to as sum types.
-Disjunctions can have any number of elements.
-<!--
-Important now we have marks, as *a | *b | c differs from *a | (*b | c).
--->
 
 These all follow from the definition of disjunction:
 - The disjunction of `a` with itself is always `a`.