cue: flx bug for len on non-concrete values
Change-Id: I7925132f01ada119a039cdec7d2a8c891f76fdc3
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3022
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/builtin.go b/cue/builtin.go
index 54367ba..d6716eb 100644
--- a/cue/builtin.go
+++ b/cue/builtin.go
@@ -27,6 +27,7 @@
"cuelang.org/go/cue/errors"
"cuelang.org/go/cue/parser"
+ "cuelang.org/go/cue/token"
"cuelang.org/go/internal"
"github.com/cockroachdb/apd/v2"
)
@@ -118,22 +119,41 @@
Result: intKind,
Func: func(c *callCtxt) {
v := c.value(0)
- switch v.Kind() {
+ switch k := v.IncompleteKind(); k {
case StructKind:
- s, _ := v.structValData(c.ctx)
+ s, err := v.structValData(c.ctx)
+ if err != nil {
+ c.ret = err
+ break
+ }
c.ret = s.Len()
case ListKind:
i := 0
- iter, _ := v.List()
+ iter, err := v.List()
+ if err != nil {
+ c.ret = err
+ break
+ }
for ; iter.Next(); i++ {
}
c.ret = i
case BytesKind:
- b, _ := v.Bytes()
+ b, err := v.Bytes()
+ if err != nil {
+ c.ret = err
+ break
+ }
c.ret = len(b)
case StringKind:
- s, _ := v.String()
+ s, err := v.String()
+ if err != nil {
+ c.ret = err
+ break
+ }
c.ret = len(s)
+ default:
+ c.ret = errors.Newf(token.NoPos,
+ "invalid argument type %v", k)
}
},
}
@@ -268,8 +288,11 @@
}
}()
x.Func(&call)
- if e, ok := call.ret.(value); ok {
- return e
+ switch v := call.ret.(type) {
+ case value:
+ return v
+ case *valueError:
+ return v.err
}
return convert(ctx, x, false, call.ret)
}
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index 92c781c..1e5cbd4 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -2182,6 +2182,43 @@
`str: string, ` +
`s2: strings.ContainsAny ("dd"), ` +
`s3: <4>.ContainsAny (<3>.str,"dd")}`,
+ }, {
+ desc: "len of incomplete types",
+ in: `
+ args: *[] | [...string]
+ v1: len(args)
+ v2: len([])
+ v3: len({})
+ v4: len({a: 3})
+ v5: len({a: 3} | {a: 4})
+ v6: len('sf' | 'dd')
+ v7: len([2] | *[1, 2])
+ v8: len([2] | [1, 2])
+ v9: len("😂")
+ v10: len("")
+ `,
+ out: `<0>{` +
+ `args: [], ` +
+ `v1: 0, ` +
+ `v2: 0, ` +
+ `v3: 0, ` +
+ `v4: 1, ` +
+ `v5: len ((<1>{a: 3} | <2>{a: 4})), ` +
+ `v6: len (('sf' | 'dd')), ` +
+ `v7: 2, ` +
+ `v8: len (([2] | [1,2])), ` +
+ `v9: 4, ` +
+ `v10: 0}`,
+ }, {
+ desc: "slice rewrite bug",
+ in: `
+ fn: {
+ arg: [...int] & [1]
+ out: arg[1:]
+ }
+ fn1: fn & {arg: [1]}
+ `,
+ out: `<0>{fn: <1>{arg: [1], out: []}, fn1: <2>{arg: [1], out: []}}`,
}}
rewriteHelper(t, testCases, evalFull)
}
@@ -2192,6 +2229,16 @@
// Don't remove. For debugging.
testCases := []testCase{{
in: `
+ fnRec: {nn: [...int], out: (fn & {arg: nn}).out}
+ fn: {
+ arg: [...int]
+
+ out: arg[0] + (fnRec & {nn: arg[1:]}).out if len(arg) > 0
+ out: 0 if len(arg) == 0
+ }
+ fn7: (fn & {arg: [1, 2, 3]}).out
+
+
`,
}}
rewriteHelper(t, testCases, evalFull)
diff --git a/cue/rewrite.go b/cue/rewrite.go
index 06171e0..ff4e7ba 100644
--- a/cue/rewrite.go
+++ b/cue/rewrite.go
@@ -130,8 +130,13 @@
func (x *sliceExpr) rewrite(ctx *context, fn rewriteFunc) value {
v := rewrite(ctx, x.x, fn)
- lo := rewrite(ctx, x.lo, fn)
- hi := rewrite(ctx, x.hi, fn)
+ var lo, hi value
+ if x.lo != nil {
+ lo = rewrite(ctx, x.lo, fn)
+ }
+ if x.hi != nil {
+ hi = rewrite(ctx, x.hi, fn)
+ }
if v == x.x && lo == x.lo && hi == x.hi {
return x
}