internal/core/adt: get default when comparing ot bottom

This is a good example that comparison to bottom is broken:
this was a bug, but should an ambiguous disjunction be an
error or not? We really need more specific builtins.

Fixes #809

Change-Id: Ia856b331dca67864421759b493f446fd0be76b29
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8902
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/testdata/comprehensions/iferror.txtar b/cue/testdata/comprehensions/iferror.txtar
index dd7403b..ee6ee4d 100644
--- a/cue/testdata/comprehensions/iferror.txtar
+++ b/cue/testdata/comprehensions/iferror.txtar
@@ -25,6 +25,31 @@
 		x
 	}
 }
+
+// Issue #809
+useDefault: {
+    a: {
+        x: *"foo" | string
+        if x != _|_ {
+             y: x
+        }
+    }
+
+    issue809: {
+        #A: {
+                a: string
+                b: *a | string
+        }
+
+        s: [Name=string]: #A & { a: Name }
+        s: bar: _
+
+        foo: [
+                for _, a in s if a.b != _|_ {a},
+        ]
+    }
+}
+
 -- out/compile --
 --- in.cue
 {
@@ -57,6 +82,33 @@
       〈1;x〉
     }
   }
+  useDefault: {
+    a: {
+      x: (*"foo"|string)
+      if (〈0;x〉 != _|_(explicit error (_|_ literal) in source)) {
+        y: 〈1;x〉
+      }
+    }
+    issue809: {
+      #A: {
+        a: string
+        b: (*〈0;a〉|string)
+      }
+      s: {
+        [string]: (〈1;#A〉 & {
+          a: 〈1;-〉
+        })
+      }
+      s: {
+        bar: _
+      }
+      foo: [
+        for _, a in 〈0;s〉 if (〈0;a〉.b != _|_(explicit error (_|_ literal) in source)) {
+          〈1;a〉
+        },
+      ]
+    }
+  }
 }
 -- out/eval --
 Errors:
@@ -91,4 +143,28 @@
       2: (int){ 3 }
     }
   }
+  useDefault: (struct){
+    a: (struct){
+      x: (string){ |(*(string){ "foo" }, (string){ string }) }
+      y: (string){ |(*(string){ "foo" }, (string){ string }) }
+    }
+    issue809: (struct){
+      #A: (#struct){
+        a: (string){ string }
+        b: (string){ string }
+      }
+      s: (struct){
+        bar: (#struct){
+          a: (string){ "bar" }
+          b: (string){ |(*(string){ "bar" }, (string){ string }) }
+        }
+      }
+      foo: (#list){
+        0: (#struct){
+          a: (string){ "bar" }
+          b: (string){ |(*(string){ "bar" }, (string){ string }) }
+        }
+      }
+    }
+  }
 }
diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go
index ed1f911..29245c0 100644
--- a/internal/core/adt/expr.go
+++ b/internal/core/adt/expr.go
@@ -1157,11 +1157,10 @@
 	}
 
 	var match bool
-	v := c.evalState(x, Partial)
 	// NOTE: using Unwrap is maybe note entirely accurate, as it may discard
 	// a future error. However, if it does so, the error will at least be
 	// reported elsewhere.
-	switch b := Unwrap(v).(type) {
+	switch b := c.value(x).(type) {
 	case nil:
 	case *Bottom:
 		if b.Code == CycleError {