cue: allow raw subsumption, taking defaults into account

Change-Id: I2046b8967147dd8383bffb45add57a0ad553898e
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9262
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/types.go b/cue/types.go
index fb8961f..d3f0dc8 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -1717,11 +1717,14 @@
 // Without options, the entire value is considered for assumption, which means
 // Subsume tests whether  v is a backwards compatible (newer) API version of w.
 //
-// Use the Final option to check subsumption if a w is known to be final,
-// and should assumed to be closed.
+// Use the Final option to check subsumption if a w is known to be final, and
+// should assumed to be closed.
 //
-// Value v and w must be obtained from the same build.
-// TODO: remove this requirement.
+// Use the Raw option to do a low-level subsumption, taking defaults into
+// account.
+//
+// Value v and w must be obtained from the same build. TODO: remove this
+// requirement.
 func (v Value) Subsume(w Value, opts ...Option) error {
 	o := getOptions(opts)
 	p := subsume.CUE
@@ -1733,7 +1736,9 @@
 	case o.ignoreClosedness:
 		p = subsume.API
 	}
-	p.Defaults = true
+	if !o.raw {
+		p.Defaults = true
+	}
 	ctx := v.ctx().opCtx
 	return p.Value(ctx, v.v, w.v)
 }
diff --git a/cue/types_test.go b/cue/types_test.go
index a327ea8..f5ab493 100644
--- a/cue/types_test.go
+++ b/cue/types_test.go
@@ -1435,6 +1435,42 @@
 		pathB:   b,
 		options: []Option{Final()},
 		want:    true,
+	}, {
+		// default
+		value: `
+		a: <5
+		b: *3 | int
+		`,
+		pathA: a,
+		pathB: b,
+		want:  true,
+	}, {
+		// Disable default elimination.
+		value: `
+			a: <5
+			b: *3 | int
+			`,
+		pathA:   a,
+		pathB:   b,
+		options: []Option{Raw()},
+		want:    false,
+	}, {
+		value: `
+			#A: {
+				exact: string
+			} | {
+				regex: string
+			}
+			#B: {
+				exact: string
+			} | {
+				regex: string
+			}
+			`,
+		pathA:   ParsePath("#A"),
+		pathB:   ParsePath("#B"),
+		options: []Option{},
+		want:    true,
 	}}
 	for _, tc := range testCases {
 		t.Run(tc.value, func(t *testing.T) {
diff --git a/internal/core/subsume/subsume.go b/internal/core/subsume/subsume.go
index 734dfdb..2c15bad 100644
--- a/internal/core/subsume/subsume.go
+++ b/internal/core/subsume/subsume.go
@@ -72,7 +72,7 @@
 	if !s.values(a, b) {
 		return s.getError()
 	}
-	return s.errs
+	return nil // ignore errors here even if there are some.
 }
 
 // Check reports whether b is an instance of a.