cue: fix bug in normalization

final normalization was not triggered if the individual values
did not change during evaluation.

Change-Id: Ib5d70c23ee872def328cea300b5b20c38a9f42e6
diff --git a/cue/eval.go b/cue/eval.go
index fa204a8..93efbd3 100644
--- a/cue/eval.go
+++ b/cue/eval.go
@@ -324,9 +324,8 @@
 			dn.add(ctx, n, v.marked)
 		}
 	}
-	// TODO: move to evaluator
 	if !changed {
-		return x
+		dn = x
 	}
 	return dn.normalize(ctx, x).val
 }
@@ -342,6 +341,7 @@
 		switch {
 		case d.marked:
 			if marked != nil {
+				// TODO: allow disjunctions to be returned as is.
 				return ctx.mkErr(x, "more than one default remaining (%v and %v)", debugStr(ctx, marked), debugStr(ctx, d.val))
 			}
 			marked = d.val.(evaluated)
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index 47cd3fc..c3d50a4 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -794,11 +794,11 @@
 		in: `
 			obj foo a: "bar"
 			obj <Name>: {
-				a: "dummy" | string
+				a: *"dummy" | string
 				sub as: a if true
 			}
 		`,
-		out: `<0>{obj: <1>{<>: <2>(Name: string)-><3>{a: ("dummy" | string) if true yield ("sub"): <4>{as: <3>.a}}, ` +
+		out: `<0>{obj: <1>{<>: <2>(Name: string)-><3>{a: (*"dummy" | string) if true yield ("sub"): <4>{as: <3>.a}}, ` +
 			`foo: <5>{a: "bar", sub: <6>{as: "bar"}}}}`,
 	}, {
 		desc: "self-reference cycles conflicts with strings",
@@ -959,7 +959,6 @@
 					name: A
 					kind: B
 				} if num < 5
-
 			}
 			a b c d: "bar"
 			`,
@@ -977,6 +976,25 @@
 			`,
 		out: `<0>{l: [int,int], l1: ["a","b"], l2: ["c","d"]}`,
 	}, {
+		desc: "normalization",
+		in: `
+			a: string | string
+			b: *1 | *int  // 1 == int(1) | float(1)
+			c: *1.0 | *float
+		`,
+		out: `<0>{a: string, b: _|_((*1 | *int):more than one default remaining (1 and int)), c: float}`,
+	}, {
+		desc: "default disambiguation",
+		in: `
+		a: *1 | int
+		b: *3 | int
+		c: a & b
+		d: b & a
+
+		e: *1 | *1
+		`,
+		out: `<0>{a: 1, b: 3, c: _|_((*1 | *3 | int):more than one default remaining (1 and 3)), d: _|_((*3 | *1 | int):more than one default remaining (3 and 1)), e: 1}`,
+	}, {
 		desc: "list comprehension",
 		in: `
 			// a: [ k for k: v in b if k < "d" if v > b.a ] // TODO test error using common iso colon
diff --git a/cue/subsume_test.go b/cue/subsume_test.go
index b0d9382..2781be5 100644
--- a/cue/subsume_test.go
+++ b/cue/subsume_test.go
@@ -23,7 +23,7 @@
 
 func TestSubsume(t *testing.T) {
 	testCases := []struct {
-		// the result of a ⊑ b, where a and b are defined in "in"
+		// the result of b ⊑ a, where a and b are defined in "in"
 		subsumes bool
 		in       string
 		mode     subsumeMode
@@ -156,10 +156,7 @@
 		87: {subsumes: true, in: `a: number, b: 2 | 1`},
 		88: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
 
-		// Disjunction TODO: for now these two are false: unifying may result in
-		// an ambiguity that we are currently not handling, so safer to not
-		// unify.
-		89: {subsumes: false, in: `a: float | number, b: 1 | 2 | 3.1`},
+		89: {subsumes: true, in: `a: float | number, b: 1 | 2 | 3.1`},
 
 		90: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
 		91: {subsumes: true, in: `a: 1 | 2, b: 1`},
diff --git a/cue/value.go b/cue/value.go
index b458284..945fe30 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -997,7 +997,7 @@
 // normalize removes redundant element from unification.
 // x must already have been evaluated.
 func (x *disjunction) normalize(ctx *context, src source) mVal {
-	less := func(ctx *context, lt, gt dValue) bool {
+	leq := func(ctx *context, lt, gt dValue) bool {
 		if isBottom(lt.val) {
 			return true
 		}
@@ -1018,7 +1018,7 @@
 			if i == j {
 				continue
 			}
-			if less(ctx, v, w) && (!less(ctx, w, v) || j < i) {
+			if leq(ctx, v, w) && (!leq(ctx, w, v) || j < i) {
 				// strictly subsumed, or equal and and the equal element was
 				// processed earlier.
 				continue outer
@@ -1027,7 +1027,7 @@
 		// If there was a three-way equality, an element w, where w == v could
 		// already have been added.
 		for j := 0; j < k; j++ {
-			if less(ctx, v, x.values[j]) {
+			if leq(ctx, v, x.values[j]) {
 				continue outer
 			}
 		}