Skip to content

Commit

Permalink
pkg/internal: fix error codes for decimal and string lists
Browse files Browse the repository at this point in the history
Fixes #585

The returned errors for decimal and string lists did not
set the correct error type, causing the errors to be
treated as fatal instead of incomplete.

Not the pretiest solution. But this code is still a leftover
from the old API. Error handling should be cleaned up
at some point. It can be greatly simplified.

Change-Id: I9f41031d055351c3f46ac1fc0e567258ec0affa9
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8208
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Jan 15, 2021
1 parent f1b1804 commit 0ffde15
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 29 deletions.
135 changes: 115 additions & 20 deletions cue/testdata/resolve/048_builtins.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
#name: builtins
#evalPartial
-- in.cue --
import (
"list"
"strings"
)

a1: {
a: and([b, c])
b: =~"oo"
Expand All @@ -18,6 +23,37 @@ o1: {
}
o2: o1 & {a: "foo"}
o3: o1 & {a: "foo", b: "baz"}

// Issue #585
stringListErrors: {
a: {
x: [string, ...string]
result: strings.Join(x, " ")
}

b: {
x: [int, ...string]
result: strings.Join(x, " ")
}

c: {
x: []
result: strings.Join(x, int)
}
}

decimalListErrors: {
a: {
x: [string]
result: list.Avg(x)
}

b: {
x: [int, ...string]
result: list.Avg(x)
}
}

-- out/def --
a1: {
a: =~"oo" & =~"fo"
Expand Down Expand Up @@ -48,19 +84,25 @@ o3: o1 & {
Errors:
o3.a: 2 errors in empty disjunction:
o3.a: conflicting values "bar" and "foo":
./in.cue:10:12
./in.cue:12:5
./in.cue:15:5
./in.cue:15:14
./in.cue:15:12
./in.cue:17:5
./in.cue:20:5
./in.cue:20:14
o3.a: conflicting values "baz" and "foo":
./in.cue:10:9
./in.cue:15:5
./in.cue:15:14
./in.cue:15:24
./in.cue:15:9
./in.cue:20:5
./in.cue:20:14
./in.cue:20:24
a3.a: invalid value "bar" (out of bound =~"oo"):
./in.cue:3:5
./in.cue:8:5
a3.a: invalid value "bar" (out of bound =~"fo"):
./in.cue:4:5
./in.cue:9:5
stringListErrors.b.result: invalid type element 0 (int) of string list argument 0:
./in.cue:31:17
stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join:
./in.cue:36:33
decimalListErrors.a.result: invalid type element 0 (string) of number list argument 0:
./in.cue:43:17

Result:
(_|_){
Expand All @@ -79,9 +121,9 @@ Result:
// [eval]
a: (_|_){
// [eval] a3.a: invalid value "bar" (out of bound =~"oo"):
// ./in.cue:3:5
// ./in.cue:8:5
// a3.a: invalid value "bar" (out of bound =~"fo"):
// ./in.cue:4:5
// ./in.cue:9:5
}
b: (string){ =~"oo" }
c: (string){ =~"fo" }
Expand All @@ -101,17 +143,70 @@ Result:
a: (_|_){
// [eval] o3.a: 2 errors in empty disjunction:
// o3.a: conflicting values "bar" and "foo":
// ./in.cue:10:12
// ./in.cue:12:5
// ./in.cue:15:5
// ./in.cue:15:14
// ./in.cue:15:12
// ./in.cue:17:5
// ./in.cue:20:5
// ./in.cue:20:14
// o3.a: conflicting values "baz" and "foo":
// ./in.cue:10:9
// ./in.cue:15:5
// ./in.cue:15:14
// ./in.cue:15:24
// ./in.cue:15:9
// ./in.cue:20:5
// ./in.cue:20:14
// ./in.cue:20:24
}
b: (string){ "baz" }
c: (string){ "bar" }
}
stringListErrors: (_|_){
// [eval]
a: (struct){
x: (list){
0: (string){ string }
}
result: (_|_){
// [incomplete] stringListErrors.a.result: non-concrete string value for element 0 of string list argument 0:
// ./in.cue:26:17
}
}
b: (_|_){
// [eval]
x: (list){
0: (int){ int }
}
result: (_|_){
// [eval] stringListErrors.b.result: invalid type element 0 (int) of string list argument 0:
// ./in.cue:31:17
}
}
c: (_|_){
// [eval]
x: (#list){
}
result: (_|_){
// [eval] stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join:
// ./in.cue:36:33
}
}
}
decimalListErrors: (_|_){
// [eval]
a: (_|_){
// [eval]
x: (#list){
0: (string){ string }
}
result: (_|_){
// [eval] decimalListErrors.a.result: invalid type element 0 (string) of number list argument 0:
// ./in.cue:43:17
}
}
b: (struct){
x: (list){
0: (int){ int }
}
result: (_|_){
// [incomplete] decimalListErrors.b.result: non-concrete number value for element 0 of number list argument 0:
// ./in.cue:48:17
}
}
}
}
2 changes: 2 additions & 0 deletions pkg/internal/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ func processErr(call *CallCtxt, errVal interface{}, ret adt.Expr) adt.Expr {
ctx := call.ctx
switch err := errVal.(type) {
case nil:
case *adt.Bottom:
ret = err
case *callError:
ret = err.b
case *json.MarshalerError:
Expand Down
37 changes: 32 additions & 5 deletions pkg/internal/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"math/big"

"cuelang.org/go/cue"
"cuelang.org/go/cue/errors"
"cuelang.org/go/cue/token"
"cuelang.org/go/internal/core/adt"
"github.com/cockroachdb/apd/v2"
Expand Down Expand Up @@ -237,7 +236,21 @@ func (c *CallCtxt) DecimalList(i int) (a []*apd.Decimal) {
return nil
}
for j := 0; v.Next(); j++ {
num, err := v.Value().Decimal()
w := v.Value()
if k := w.IncompleteKind(); k&adt.NumKind == 0 {
err := c.ctx.NewErrf(
"invalid type element %d (%s) of number list argument %d", j, k, i)
c.Err = &callError{err}
break
}
if !w.IsConcrete() {
err := c.ctx.NewErrf(
"non-concrete number value for element %d of number list argument %d", j, i)
err.Code = adt.IncompleteError
c.Err = &callError{err}
break
}
num, err := w.Decimal()
if err != nil {
c.errf(c.src, err, "invalid list element %d in argument %d to %s: %v",
j, i, c.Name(), err)
Expand All @@ -257,10 +270,24 @@ func (c *CallCtxt) StringList(i int) (a []string) {
return nil
}
for j := 0; v.Next(); j++ {
str, err := v.Value().String()
w := v.Value()
if k := w.IncompleteKind(); k&adt.StringKind == 0 {
err := c.ctx.NewErrf(
"invalid type element %d (%s) of string list argument %d", j, k, i)
c.Err = &callError{err}
break
}
if !w.IsConcrete() {
err := c.ctx.NewErrf(
"non-concrete string value for element %d of string list argument %d", j, i)
err.Code = adt.IncompleteError
c.Err = &callError{err}
break
}
str, err := w.String()
if err != nil {
c.Err = errors.Wrapf(err, c.Pos(),
"element %d of list argument %d", j, i)
// TODO: expose wrapping
c.Err = &callError{c.ctx.NewErrf("element %d of list argument %d: %v", j, i, err)}
break
}
a = append(a, str)
Expand Down
5 changes: 3 additions & 2 deletions pkg/list/testdata/gen.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ error in call to list.Slice: invalid index: 3 > 1
error in call to list.Slice: negative index
error in call to list.Slice: slice bounds out of range
error in call to list.Take: negative index
0: error in call to list.SortStrings: element 0 of list argument 0: cannot use value 1 (type int) as string
Ascending.x: error in call to list.Sort: 2 errors in empty disjunction:
Ascending.x: error in call to list.Sort: conflicting values number and {b:2} (mismatched types number and struct)
Ascending.x: error in call to list.Sort: conflicting values string and {b:2} (mismatched types string and struct)
Expand All @@ -92,6 +91,8 @@ t20: cannot use "foo" (type string) as list in argument 1 to list.Min:
./in.cue:22:15
t23: cannot use "foo" (type string) as list in argument 1 to list.Product:
./in.cue:25:19
t42: invalid type element 0 (int) of string list argument 0:
./in.cue:48:6
t45: cannot use "foo" (type string) as list in argument 1 to list.Sum:
./in.cue:51:15

Expand Down Expand Up @@ -146,7 +147,7 @@ t39: [{
}]
t40: _|_ // error in call to list.Sort: Ascending.x: 2 errors in empty disjunction: (and 11 more errors)
t41: ["a", "b"]
t42: _|_ // error in call to list.SortStrings: element 0 of list argument 0: 0: cannot use value 1 (type int) as string (and 1 more errors)
t42: _|_ // t42: invalid type element 0 (int) of string list argument 0 (and 1 more errors)
t43: 10
t44: 0
t45: _|_ // t45: cannot use "foo" (type string) as list in argument 1 to list.Sum
Expand Down
5 changes: 3 additions & 2 deletions pkg/strings/testdata/gen.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ t16: strings.MaxRunes(3) & "hello"
t17: strings.MinRunes(10) & "hello"
-- out/strings --
Errors:
0: error in call to strings.Join: element 0 of list argument 0: cannot use value 1 (type int) as string
t2: invalid type element 0 (int) of string list argument 0:
./in.cue:4:5
t10: invalid value "quux" (does not satisfy strings.MaxRunes(3)):
./in.cue:12:6
./in.cue:12:23
Expand All @@ -38,7 +39,7 @@ t17: invalid value "hello" (does not satisfy strings.MinRunes(10)):

Result:
t1: "Hello World!"
t2: _|_ // error in call to strings.Join: element 0 of list argument 0: 0: cannot use value 1 (type int) as string (and 1 more errors)
t2: _|_ // t2: invalid type element 0 (int) of string list argument 0 (and 1 more errors)
t3: 97
t4: 'llo'
t5: "✓ H"
Expand Down

0 comments on commit 0ffde15

Please sign in to comment.