internal/core: fix incorrect error handling
1: don't double-wrap errors in BinOp. This could happen
when a value is passed as a Vertex in API usage.
2: subsumption incorrectly used And op for BinOp.
Together these Fixes #461
This also improves reporting of structural errors,
although this is not complete and not the goal of
this CL.
Change-Id: Id021a0eb4fa5628f56167d2fccea7d99dbddf390
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7065
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/testdata/script/issue461.txt b/cmd/cue/cmd/testdata/script/issue461.txt
new file mode 100644
index 0000000..a95d002
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/issue461.txt
@@ -0,0 +1,26 @@
+cue cmd writefile
+
+-- cue.mod/module.cue --
+module: "mod.com"
+-- expect-hello --
+Hello, world!
+-- x_tool.cue --
+package x
+
+import (
+ "strings"
+ "tool/exec"
+ "tool/file"
+)
+
+command: writefile: {
+ echo: exec.Run & {
+ cmd: "echo hello.txt"
+ stdout: string
+ }
+
+ write: file.Create & {
+ filename: strings.TrimSpace(echo.stdout)
+ contents: "Hello, world!"
+ }
+}
diff --git a/cue/testdata/cycle/structural.txtar b/cue/testdata/cycle/structural.txtar
index 678384c..0f76200 100644
--- a/cue/testdata/cycle/structural.txtar
+++ b/cue/testdata/cycle/structural.txtar
@@ -84,7 +84,7 @@
}
d3: {
- // TODO(errors): position reporting in structural cycle.
+ // TODO(errors): correct position reporting in structural cycle.
config: {
a: b: c: indirect
indirect: [a.b, null][i]
@@ -253,6 +253,8 @@
./in.cue:79:8
d2.r: structural cycle:
./in.cue:79:8
+0: structural cycle:
+ ./in.cue:89:19
Result:
(_|_){
@@ -507,12 +509,14 @@
b: (_|_){
// [structural cycle]
c: (_|_){
- // [structural cycle]
+ // [structural cycle] 0: structural cycle:
+ // ./in.cue:89:19
}
}
}
indirect: (_|_){
- // [structural cycle]
+ // [structural cycle] 0: structural cycle:
+ // ./in.cue:89:19
}
i: (int){ 1 }
}
@@ -523,12 +527,14 @@
b: (_|_){
// [structural cycle]
c: (_|_){
- // [structural cycle]
+ // [structural cycle] 0: structural cycle:
+ // ./in.cue:89:19
}
}
}
indirect: (_|_){
- // [structural cycle]
+ // [structural cycle] 0: structural cycle:
+ // ./in.cue:89:19
}
i: (int){ 0 }
}
diff --git a/internal/core/adt/binop.go b/internal/core/adt/binop.go
index 7edd191..b43bea6 100644
--- a/internal/core/adt/binop.go
+++ b/internal/core/adt/binop.go
@@ -51,11 +51,8 @@
}
}
- if a, ok := left.(*Bottom); ok {
- return CombineErrors(nil, a, right)
- }
- if b, ok := left.(*Bottom); ok {
- return b
+ if err := CombineErrors(c.src, left, right); err != nil {
+ return err
}
switch op {
diff --git a/internal/core/adt/errors.go b/internal/core/adt/errors.go
index 4736dbb..1f54c86 100644
--- a/internal/core/adt/errors.go
+++ b/internal/core/adt/errors.go
@@ -171,8 +171,8 @@
// CombineErrors combines two errors that originate at the same Vertex.
func CombineErrors(src ast.Node, x, y Value) *Bottom {
- a, _ := x.(*Bottom)
- b, _ := y.(*Bottom)
+ a, _ := Unwrap(x).(*Bottom)
+ b, _ := Unwrap(y).(*Bottom)
switch {
case a != nil && b != nil:
diff --git a/internal/core/subsume/subsume.go b/internal/core/subsume/subsume.go
index 9ce210a..ba00aab 100644
--- a/internal/core/subsume/subsume.go
+++ b/internal/core/subsume/subsume.go
@@ -103,6 +103,13 @@
s.errs = errors.Append(s.errs, b.Err)
}
+func unifyValue(c *adt.OpContext, a, b adt.Value) adt.Value {
+ v := &adt.Vertex{}
+ v.AddConjunct(adt.MakeRootConjunct(c.Env(0), a))
+ v.AddConjunct(adt.MakeRootConjunct(c.Env(0), b))
+ return c.Unifier.Evaluate(c, v)
+}
+
func (s *subsumer) getError() (err errors.Error) {
c := s.ctx
// src := binSrc(token.NoPos, opUnify, gt, lt)
@@ -110,7 +117,7 @@
// src := binSrc(token.NoPos, opUnify, s.gt, s.lt)
if s.missing != 0 {
s.errf("missing field %q", s.missing.SelectorString(c))
- } else if b, ok := adt.BinOp(c, adt.AndOp, s.gt, s.lt).(*adt.Bottom); !ok {
+ } else if b, ok := unifyValue(c, s.gt, s.lt).(*adt.Bottom); !ok {
s.errf("value not an instance")
} else {
s.errs = errors.Append(s.errs, b.Err)