pkg/internal: fix error codes for decimal and string lists

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>
diff --git a/cue/testdata/resolve/048_builtins.txtar b/cue/testdata/resolve/048_builtins.txtar
index cc7e94b..70466cc 100644
--- a/cue/testdata/resolve/048_builtins.txtar
+++ b/cue/testdata/resolve/048_builtins.txtar
@@ -3,6 +3,11 @@
 #name: builtins
 #evalPartial
 -- in.cue --
+import (
+  "list"
+  "strings"
+)
+
 a1: {
 	a: and([b, c])
 	b: =~"oo"
@@ -18,6 +23,37 @@
 }
 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"
@@ -48,19 +84,25 @@
 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:
 (_|_){
@@ -79,9 +121,9 @@
     // [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" }
@@ -101,17 +143,70 @@
     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
+      }
+    }
+  }
 }
diff --git a/pkg/internal/builtin.go b/pkg/internal/builtin.go
index 7105378..13a034e 100644
--- a/pkg/internal/builtin.go
+++ b/pkg/internal/builtin.go
@@ -207,6 +207,8 @@
 	ctx := call.ctx
 	switch err := errVal.(type) {
 	case nil:
+	case *adt.Bottom:
+		ret = err
 	case *callError:
 		ret = err.b
 	case *json.MarshalerError:
diff --git a/pkg/internal/context.go b/pkg/internal/context.go
index d437aa3..8f0e1af 100644
--- a/pkg/internal/context.go
+++ b/pkg/internal/context.go
@@ -19,7 +19,6 @@
 	"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"
@@ -237,7 +236,21 @@
 		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)
@@ -257,10 +270,24 @@
 		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)
diff --git a/pkg/list/testdata/gen.txtar b/pkg/list/testdata/gen.txtar
index 400e223..90269d4 100644
--- a/pkg/list/testdata/gen.txtar
+++ b/pkg/list/testdata/gen.txtar
@@ -75,7 +75,6 @@
 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)
@@ -92,6 +91,8 @@
     ./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
 
@@ -146,7 +147,7 @@
 }]
 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
diff --git a/pkg/strings/testdata/gen.txtar b/pkg/strings/testdata/gen.txtar
index 636fd38..5977669 100644
--- a/pkg/strings/testdata/gen.txtar
+++ b/pkg/strings/testdata/gen.txtar
@@ -22,7 +22,8 @@
 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
@@ -38,7 +39,7 @@
 
 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"