cue: fix comparing against bottom
May only be against a verbatim error.
Change-Id: I82faa0031cc2b39b7a2e2114c07289de74c5ad88
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3766
Reviewed-by: roger peppe <rogpeppe@gmail.com>
diff --git a/cue/ast.go b/cue/ast.go
index 263cee6..35ce5c6 100644
--- a/cue/ast.go
+++ b/cue/ast.go
@@ -496,7 +496,7 @@
case *ast.BottomLit:
// TODO: record inline comment.
- ret = &bottom{baseValue: newExpr(n), format: "from source"}
+ ret = &bottom{baseValue: newExpr(n), code: codeUser, format: "from source"}
case *ast.BadDecl:
// nothing to do
diff --git a/cue/errors.go b/cue/errors.go
index a3ce783..98af40e 100644
--- a/cue/errors.go
+++ b/cue/errors.go
@@ -100,6 +100,7 @@
codeNotExist
codeTypeError
codeIncomplete
+ codeUser
codeCycle
)
@@ -110,6 +111,13 @@
return false
}
+func isLiteralBottom(v value) bool {
+ if err, ok := v.(*bottom); ok {
+ return err.code == codeUser
+ }
+ return false
+}
+
var errNotExists = &bottom{code: codeNotExist, format: "undefined value"}
func exists(v value) bool {
diff --git a/cue/eval.go b/cue/eval.go
index 59e1ffd..04a9c77 100644
--- a/cue/eval.go
+++ b/cue/eval.go
@@ -428,7 +428,7 @@
// principled perhaps. One should especially take care that two values
// evaluating to bottom don't evaluate to true. For now we check for
// bottom here and require that one of the values be a bottom literal.
- if l, r := isBottom(x.left), isBottom(x.right); l || r {
+ if isLiteralBottom(x.left) || isLiteralBottom(x.right) {
leftBottom := isBottom(left)
rightBottom := isBottom(right)
switch x.op {
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index 3e1aab0..9582f78 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -2444,6 +2444,19 @@
}}
`,
out: `<0>{a: <1>{<>: <2>(Name: string)-><3>{info :: <4>C{X: "foo"}}, d: <5>C{info :: <6>C{X: "foo"}, Y: "foo"}}, base :: <7>C{info :: <8>{...}}}`,
+ }, {
+ desc: "comparison against bottom",
+ in: `
+ a: _|_ == _|_
+ b: err == 1&2 // not a literal error, so not allowed
+ c: err == _|_ // allowed
+ d: err != _|_ // allowed
+ e: err != 1&3
+ // z: err == err // TODO: should infer to be true?
+
+ err: 1 & 2
+ `,
+ out: `<0>{a: true, b: _|_((1 & 2):conflicting values 1 and 2), err: _|_((1 & 2):conflicting values 1 and 2), c: true, d: false, e: _|_((1 & 2):conflicting values 1 and 2)}`,
}}
rewriteHelper(t, testCases, evalFull)
}
diff --git a/cue/rewrite_test.go b/cue/rewrite_test.go
index 2673e41..bbf3288 100644
--- a/cue/rewrite_test.go
+++ b/cue/rewrite_test.go
@@ -75,7 +75,7 @@
t = v
}
emit := testResolve(ctx, x.emit, m)
- obj := &structLit{x.baseValue, emit, t, x.closeStatus, nil, arcs, nil}
+ obj := &structLit{x.baseValue, emit, t, x.closeStatus, x.comprehensions, arcs, nil}
return obj
case *list:
elm := rewriteRec(ctx, x.elem, x.elem, m).(*structLit)