Skip to content

Commit f06f781

Browse files
committed
cue: improve error messages
- more Go-style error messages - report original value and type level - remove struct IDs from printed structs - more context information overall Note: this is only a partial update. Errors relating to disjunctions, for instance, need a lot more love. Change-Id: I9025a2cace8b38a987e4de3e73620bea734b7414 Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2580 Reviewed-by: Marcel van Lohuizen <[email protected]>
1 parent 4e5b69a commit f06f781

25 files changed

+397
-301
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
sum:more than one element remaining (1 and 2):
1+
sum: more than one element remaining (1 and 2):
22
./testdata/partial/partial.cue:4:6
3-
b.idx:invalid non-ground value string (must be concrete int|string):
3+
b.idx: invalid non-ground value string (must be concrete int|string):
44
./testdata/partial/partial.cue:7:9
5-
b.str:incomplete value (string):
5+
b.str: incomplete value (string):
66
./testdata/partial/partial.cue:8:7
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
text:unsupported op &(int, string):
1+
text: conflicting values 42 and string (mismatched types int and string):
22
./testdata/tasks/task_tool.cue:29:9
33
tool/cli:4:9

cue/binop.go

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package cue
1616

1717
import (
1818
"bytes"
19+
"fmt"
1920
"math/big"
2021
"regexp"
2122
"sort"
@@ -54,9 +55,27 @@ func binOp(ctx *context, src source, op op, left, right evaluated) (result evalu
5455

5556
leftKind := left.kind()
5657
rightKind := right.kind()
57-
kind, invert := matchBinOpKind(op, leftKind, rightKind)
58+
kind, invert, msg := matchBinOpKind(op, leftKind, rightKind)
5859
if kind == bottomKind {
59-
return ctx.mkIncompatible(src, op, left, right)
60+
simplify := func(v, orig value) value {
61+
switch x := v.(type) {
62+
case *disjunction:
63+
return orig
64+
case *binaryExpr:
65+
if x.op == opDisjunction {
66+
return orig
67+
}
68+
default:
69+
return x
70+
}
71+
return v
72+
}
73+
var l, r value = left, right
74+
if x, ok := src.(*binaryExpr); ok {
75+
l = simplify(x.left, left)
76+
r = simplify(x.right, right)
77+
}
78+
return ctx.mkErr(src, msg, op, ctx.str(l), ctx.str(r), leftKind, rightKind)
6079
}
6180
if kind.hasReferences() {
6281
panic("unexpected references in expression")
@@ -274,14 +293,14 @@ func errOutOfBounds(ctx *context, pos token.Pos, r *bound, v evaluated) *bottom
274293
pos = r.Pos()
275294
}
276295
e := mkBin(ctx, pos, opUnify, r, v)
277-
msg := "%v not within bound %v"
296+
msg := "invalid value %v (out of bound %v)"
278297
switch r.op {
279298
case opNeq, opNMat:
280-
msg = "%v excluded by %v"
299+
msg = "invalid value %v (excluded by %v)"
281300
case opMat:
282-
msg = "%v does not match %v"
301+
msg = "invalid value %v (does not match %v)"
283302
}
284-
return ctx.mkErr(e, msg, debugStr(ctx, v), debugStr(ctx, r))
303+
return ctx.mkErr(e, msg, ctx.str(v), ctx.str(r))
285304
}
286305

287306
func opInfo(op op) (cmp op, norm int) {
@@ -310,8 +329,9 @@ func (x *bound) binOp(ctx *context, src source, op op, other evaluated) evaluate
310329
newSrc := binSrc(src.Pos(), op, x, other)
311330
switch op {
312331
case opUnify:
313-
k, _ := matchBinOpKind(opUnify, x.kind(), other.kind())
332+
k, _, msg := matchBinOpKind(opUnify, x.kind(), other.kind())
314333
if k == bottomKind {
334+
return ctx.mkErr(src, msg, opUnify, ctx.str(x), ctx.str(other), x.kind(), other.kind())
315335
break
316336
}
317337
switch y := other.(type) {
@@ -433,8 +453,8 @@ func (x *bound) binOp(ctx *context, src source, op op, other evaluated) evaluate
433453
fallthrough
434454

435455
case d.Negative:
436-
return ctx.mkErr(newSrc, "incompatible bounds %v and %v",
437-
debugStr(ctx, x), debugStr(ctx, y))
456+
return ctx.mkErr(newSrc, "conflicting bounds %v and %v",
457+
ctx.str(x), ctx.str(y))
438458
}
439459

440460
case x.op == opNeq:
@@ -477,8 +497,9 @@ func (x *customValidator) binOp(ctx *context, src source, op op, other evaluated
477497
newSrc := binSrc(src.Pos(), op, x, other)
478498
switch op {
479499
case opUnify:
480-
k, _ := matchBinOpKind(opUnify, x.kind(), other.kind())
500+
k, _, msg := matchBinOpKind(opUnify, x.kind(), other.kind())
481501
if k == bottomKind {
502+
return ctx.mkErr(src, msg, op, ctx.str(x), ctx.str(other), x.kind(), other.kind())
482503
break
483504
}
484505
switch y := other.(type) {
@@ -513,7 +534,7 @@ func (x *customValidator) binOp(ctx *context, src source, op op, other evaluated
513534
return y
514535
}
515536
}
516-
return ctx.mkIncompatible(src, op, x, other)
537+
return ctx.mkErr(src, "invalid operation %v and %v (operator not defined for custom validator)")
517538
}
518539

519540
func (x *customValidator) check(ctx *context, v evaluated) evaluated {
@@ -531,13 +552,13 @@ func (x *customValidator) check(ctx *context, v evaluated) evaluated {
531552
return ctx.mkErr(x, "invalid custom validator")
532553
} else if !b.b {
533554
var buf bytes.Buffer
534-
buf.WriteString(x.call.Name)
555+
fmt.Fprintf(&buf, "%s.%s", ctx.labelStr(x.call.pkg), x.call.Name)
535556
buf.WriteString("(")
536557
for _, a := range x.args {
537-
buf.WriteString(debugStr(ctx, a))
558+
buf.WriteString(ctx.str(a))
538559
}
539560
buf.WriteString(")")
540-
return ctx.mkErr(x, "value %v not in %v", debugStr(ctx, v), buf.String())
561+
return ctx.mkErr(x, "invalid value %s (does not satisfy %s)", ctx.str(v), buf.String())
541562
}
542563
return nil
543564
}
@@ -681,7 +702,7 @@ func (x *boolLit) binOp(ctx *context, src source, op op, other evaluated) evalua
681702
switch op {
682703
case opUnify:
683704
if x.b != y.b {
684-
return ctx.mkErr(x, "conflicting values: %v != %v", x.b, y.b)
705+
return ctx.mkErr(x, "conflicting values %v and %v", x.b, y.b)
685706
}
686707
return x
687708
case opLand:
@@ -711,7 +732,8 @@ func (x *stringLit) binOp(ctx *context, src source, op op, other evaluated) eval
711732
str := other.strValue()
712733
if x.str != str {
713734
src := mkBin(ctx, src.Pos(), op, x, other)
714-
return ctx.mkErr(src, "conflicting values: %v != %v", x.str, str)
735+
return ctx.mkErr(src, "conflicting values %v and %v",
736+
ctx.str(x), ctx.str(y))
715737
}
716738
return x
717739
case opLss, opLeq, opEql, opNeq, opGeq, opGtr:
@@ -762,7 +784,8 @@ func (x *bytesLit) binOp(ctx *context, src source, op op, other evaluated) evalu
762784
switch op {
763785
case opUnify:
764786
if !bytes.Equal(x.b, b) {
765-
return ctx.mkErr(x, "conflicting values: %v != %v", x.b, b)
787+
return ctx.mkErr(x, "conflicting values %v and %v",
788+
ctx.str(x), ctx.str(y))
766789
}
767790
return x
768791
case opLss, opLeq, opEql, opNeq, opGeq, opGtr:
@@ -867,7 +890,8 @@ func (x *numLit) binOp(ctx *context, src source, op op, other evaluated) evaluat
867890
case opUnify:
868891
if x.v.Cmp(&y.v) != 0 {
869892
src = mkBin(ctx, src.Pos(), op, x, other)
870-
return ctx.mkErr(src, "conflicting values: %v != %v", x.strValue(), y.strValue())
893+
return ctx.mkErr(src, "conflicting values %v and %v",
894+
ctx.str(x), ctx.str(y))
871895
}
872896
if k != x.k {
873897
n.v = x.v
@@ -1010,7 +1034,7 @@ func (x *list) binOp(ctx *context, src source, op op, other evaluated) evaluated
10101034
n := unify(ctx, src, x.len.(evaluated), y.len.(evaluated))
10111035
if isBottom(n) {
10121036
src = mkBin(ctx, src.Pos(), op, x, other)
1013-
return ctx.mkErr(src, "incompatible list lengths: %v", n)
1037+
return ctx.mkErr(src, "conflicting list lengths: %v", n)
10141038
}
10151039
sx := x.elem.arcs
10161040
xa := sx
@@ -1026,10 +1050,10 @@ func (x *list) binOp(ctx *context, src source, op op, other evaluated) evaluated
10261050
typ := x.typ
10271051
max, ok := n.(*numLit)
10281052
if !ok || len(xa) < max.intValue(ctx) {
1053+
src := mkBin(ctx, src.Pos(), op, x.typ, y.typ)
10291054
typ = unify(ctx, src, x.typ.(evaluated), y.typ.(evaluated))
10301055
if isBottom(typ) {
1031-
src = mkBin(ctx, src.Pos(), op, x, other)
1032-
return ctx.mkErr(src, "incompatible list types: %v: ", typ)
1056+
return ctx.mkErr(src, "conflicting list element types: %v", typ)
10331057
}
10341058
}
10351059

cue/build_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func TestBuild(t *testing.T) {
7979
emit string
8080
}{{
8181
insts(&bimport{"", files(`test: "ok"`)}),
82-
`<0>{test: "ok"}`,
82+
`{test: "ok"}`,
8383
// }, {
8484
// insts(pkg1, &bimport{"",
8585
// files(

0 commit comments

Comments
 (0)