pkg: clean up builtin errors

- delete dead code and unused fields
- remove unused arguments
- dedup errors
- use OpContext-based error methods (for positions)

Fixes #902
Issue #52

Change-Id: Idf96e569400a6a5230a8783b0881a895026a41ae
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9449
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/cue/testdata/comprehensions/fields.txtar b/cue/testdata/comprehensions/fields.txtar
index 8cf3a10..1974d3c 100644
--- a/cue/testdata/comprehensions/fields.txtar
+++ b/cue/testdata/comprehensions/fields.txtar
@@ -25,7 +25,8 @@
   #User: (#struct){
     tags_str: (string){ string }
     tags_map: (_|_){
-      // [incomplete] error in call to strings.Split: non-concrete value string
+      // [incomplete] error in call to strings.Split: non-concrete value string:
+      //     ./in.cue:6:22
       "{a}": (string){ string }
     }
   }
diff --git a/cue/testdata/cycle/compbottomnofinal.txtar b/cue/testdata/cycle/compbottomnofinal.txtar
index df23d04..c19238d 100644
--- a/cue/testdata/cycle/compbottomnofinal.txtar
+++ b/cue/testdata/cycle/compbottomnofinal.txtar
@@ -359,7 +359,6 @@
 }
 -- out/eval --
 Errors:
-error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax
 large.p1.Y: cycle: new field port inserted by if clause that was previously evaluated by another if clause
 large.p2.#Y: cycle: field userinfo was added after an if clause evaluated it
 large.p2.Y: cycle: new field port inserted by if clause that was previously evaluated by another if clause
@@ -372,6 +371,16 @@
 medium.p4.Y: cycle: new field port inserted by if clause that was previously evaluated by another if clause
 minimal.b: cycle: new field port inserted by if clause that was previously evaluated by another if clause
 small.p1.#Y: cycle: field port was added after an if clause evaluated it
+error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+    ./in.cue:104:23
+error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+    ./in.cue:126:23
+error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+    ./in.cue:228:23
+error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+    ./in.cue:269:23
+error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+    ./in.cue:310:23
 
 Result:
 (_|_){
@@ -441,7 +450,8 @@
       Y: (_|_){
         // [eval] medium.p3.Y: cycle: new field port inserted by if clause that was previously evaluated by another if clause
         port: (_|_){
-          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax
+          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+          //     ./in.cue:104:23
         }
       }
       #Y: (#struct){
@@ -456,7 +466,8 @@
       Y: (_|_){
         // [eval] medium.p4.Y: cycle: new field port inserted by if clause that was previously evaluated by another if clause
         port: (_|_){
-          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax
+          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+          //     ./in.cue:126:23
         }
       }
       #X: (#struct){
@@ -501,7 +512,8 @@
         userinfo: (string){ "user" }
         host: (string){ "example.com" }
         port: (_|_){
-          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax
+          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+          //     ./in.cue:228:23
         }
       }
       X: (string){ "user@example.com" }
@@ -524,7 +536,8 @@
         userinfo: (string){ "user" }
         host: (string){ "example.com" }
         port: (_|_){
-          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax
+          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+          //     ./in.cue:269:23
         }
       }
       #X: (#struct){
@@ -552,7 +565,8 @@
         userinfo: (string){ "user" }
         host: (string){ "example.com" }
         port: (_|_){
-          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax
+          // [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
+          //     ./in.cue:310:23
         }
       }
       #Y: (_|_){
diff --git a/cue/testdata/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar b/cue/testdata/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar
index ec3b2c0..243fe7f 100644
--- a/cue/testdata/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar
+++ b/cue/testdata/fulleval/026_dont_convert_incomplete_errors_to_non-incomplete.txtar
@@ -92,7 +92,8 @@
   }
   s2: (string){ strings.ContainsAny("dd") }
   s3: (_|_){
-    // [incomplete] error in call to strings.ContainsAny: non-concrete value string
+    // [incomplete] error in call to strings.ContainsAny: non-concrete value string:
+    //     ./in.cue:15:5
   }
   str: (string){ string }
   num: (number){ <4 }
diff --git "a/cue/testdata/fulleval/044_Issue_\043178.txtar" "b/cue/testdata/fulleval/044_Issue_\043178.txtar"
index 7819fe1..9f19668 100644
--- "a/cue/testdata/fulleval/044_Issue_\043178.txtar"
+++ "b/cue/testdata/fulleval/044_Issue_\043178.txtar"
@@ -27,12 +27,14 @@
 -- out/eval --
 (struct){
   foo: (_|_){
-    // [incomplete] error in call to encoding/csv.Decode: non-concrete value bytes
+    // [incomplete] error in call to encoding/csv.Decode: non-concrete value bytes:
+    //     ./in.cue:5:7
   }
   data: (bytes){ bytes }
   len: (int){ int }
   bar: (_|_){
-    // [incomplete] error in call to encoding/hex.EncodedLen: non-concrete value int
+    // [incomplete] error in call to encoding/hex.EncodedLen: non-concrete value int:
+    //     ./in.cue:9:6
   }
 }
 -- out/compile --
diff --git a/cue/testdata/fulleval/056_issue314.txtar b/cue/testdata/fulleval/056_issue314.txtar
index 2df1a8b..d1c6876 100644
--- a/cue/testdata/fulleval/056_issue314.txtar
+++ b/cue/testdata/fulleval/056_issue314.txtar
@@ -84,7 +84,8 @@
   #T: (#struct){
     s: (string){ string }
     out: (_|_){
-      // [incomplete] error in call to text/template.Execute: cannot convert incomplete value "string" to JSON
+      // [incomplete] error in call to text/template.Execute: cannot convert incomplete value "string" to JSON:
+      //     ./in.cue:14:7
     }
   }
   #V: (#struct){
diff --git a/cue/testdata/resolve/048_builtins.txtar b/cue/testdata/resolve/048_builtins.txtar
index ac56168..3b845e8 100644
--- a/cue/testdata/resolve/048_builtins.txtar
+++ b/cue/testdata/resolve/048_builtins.txtar
@@ -99,12 +99,14 @@
 a3.a: invalid value "bar" (out of bound =~"fo"):
     ./in.cue:9:5
     ./in.cue:12:14
-stringListErrors.b.result: invalid type element 0 (int) of string list argument 0:
+stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string:
     ./in.cue:31:17
+    ./in.cue:30:13
 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:
+decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number:
     ./in.cue:43:17
+    ./in.cue:42:13
 
 Result:
 (_|_){
@@ -167,8 +169,9 @@
         0: (string){ string }
       }
       result: (_|_){
-        // [incomplete] stringListErrors.a.result: non-concrete string value for element 0 of string list argument 0:
+        // [incomplete] stringListErrors.a.result: non-concrete value string for element 0 of string list argument 0:
         //     ./in.cue:26:17
+        //     ./in.cue:25:13
       }
     }
     b: (_|_){
@@ -177,8 +180,9 @@
         0: (int){ int }
       }
       result: (_|_){
-        // [eval] stringListErrors.b.result: invalid type element 0 (int) of string list argument 0:
+        // [eval] stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string:
         //     ./in.cue:31:17
+        //     ./in.cue:30:13
       }
     }
     c: (_|_){
@@ -199,8 +203,9 @@
         0: (string){ string }
       }
       result: (_|_){
-        // [eval] decimalListErrors.a.result: invalid type element 0 (string) of number list argument 0:
+        // [eval] decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number:
         //     ./in.cue:43:17
+        //     ./in.cue:42:13
       }
     }
     b: (struct){
@@ -208,8 +213,9 @@
         0: (int){ int }
       }
       result: (_|_){
-        // [incomplete] decimalListErrors.b.result: non-concrete number value for element 0 of number list argument 0:
+        // [incomplete] decimalListErrors.b.result: non-concrete value int for element 0 of number list argument 0:
         //     ./in.cue:48:17
+        //     ./in.cue:47:13
       }
     }
   }
diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go
index 60e6b82..d5796f3 100644
--- a/internal/core/adt/context.go
+++ b/internal/core/adt/context.go
@@ -585,8 +585,7 @@
 		if b, ok := result.(*Bottom); ok {
 			if c.src != nil &&
 				b.Code == CycleError &&
-				b.Err.Position() == token.NoPos &&
-				len(b.Err.InputPositions()) == 0 {
+				len(errors.Positions(b.Err)) == 0 {
 				bb := *b
 				bb.Err = errors.Wrapf(b.Err, c.src.Pos(), "")
 				result = &bb
diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go
index 714b815..67933fa 100644
--- a/internal/core/adt/expr.go
+++ b/internal/core/adt/expr.go
@@ -1398,6 +1398,7 @@
 				c.addErrf(0, pos(a),
 					"cannot use %s as %s in argument %d to %s",
 					a, v, i+1, fun)
+				return nil
 			}
 			args[i] = n
 		}
diff --git a/pkg/encoding/base64/manual.go b/pkg/encoding/base64/manual.go
index b292424..f5f3aae 100644
--- a/pkg/encoding/base64/manual.go
+++ b/pkg/encoding/base64/manual.go
@@ -17,9 +17,10 @@
 
 import (
 	"encoding/base64"
-	"fmt"
 
 	"cuelang.org/go/cue"
+	"cuelang.org/go/cue/errors"
+	"cuelang.org/go/cue/token"
 )
 
 // EncodedLen returns the length in bytes of the base64 encoding
@@ -27,7 +28,7 @@
 // as only StdEncoding is supported for now.
 func EncodedLen(encoding cue.Value, n int) (int, error) {
 	if err := encoding.Null(); err != nil {
-		return 0, fmt.Errorf("base64: unsupported encoding: %v", err)
+		return 0, errors.Wrapf(err, token.NoPos, "base64: unsupported encoding")
 	}
 	return base64.StdEncoding.EncodedLen(n), nil
 }
@@ -37,7 +38,7 @@
 // null as only StdEncoding is supported for now.
 func DecodedLen(encoding cue.Value, x int) (int, error) {
 	if err := encoding.Null(); err != nil {
-		return 0, fmt.Errorf("base64: unsupported encoding: %v", err)
+		return 0, errors.Wrapf(err, token.NoPos, "base64: unsupported encoding")
 	}
 	return base64.StdEncoding.DecodedLen(x), nil
 }
@@ -46,7 +47,7 @@
 // as only StdEncoding is supported for now.
 func Encode(encoding cue.Value, src []byte) (string, error) {
 	if err := encoding.Null(); err != nil {
-		return "", fmt.Errorf("base64: unsupported encoding: %v", err)
+		return "", errors.Wrapf(err, token.NoPos, "base64: unsupported encoding")
 	}
 	return base64.StdEncoding.EncodeToString(src), nil
 }
@@ -55,7 +56,7 @@
 // to be set to null as only StdEncoding is supported for now.
 func Decode(encoding cue.Value, s string) ([]byte, error) {
 	if err := encoding.Null(); err != nil {
-		return nil, fmt.Errorf("base64: unsupported encoding: %v", err)
+		return nil, errors.Wrapf(err, token.NoPos, "base64: unsupported encoding")
 	}
 	return base64.StdEncoding.DecodeString(s)
 }
diff --git a/pkg/encoding/base64/testdata/gen.txtar b/pkg/encoding/base64/testdata/gen.txtar
index 8ad720a..7c3707f 100644
--- a/pkg/encoding/base64/testdata/gen.txtar
+++ b/pkg/encoding/base64/testdata/gen.txtar
@@ -9,8 +9,10 @@
 t4: base64.Decode({}, "foo")
 -- out/base64 --
 Errors:
-error in call to encoding/base64.Decode: base64: unsupported encoding: cannot use value {} (type struct) as null
-error in call to encoding/base64.Decode: illegal base64 data at input byte 0
+error in call to encoding/base64.Decode: illegal base64 data at input byte 0:
+    ./in.cue:5:5
+error in call to encoding/base64.Decode: base64: unsupported encoding: cannot use value {} (type struct) as null:
+    ./in.cue:6:5
 
 Result:
 t1: "Zm9v"
diff --git a/pkg/encoding/hex/testdata/gen.txtar b/pkg/encoding/hex/testdata/gen.txtar
index 45a951c..1b82694 100644
--- a/pkg/encoding/hex/testdata/gen.txtar
+++ b/pkg/encoding/hex/testdata/gen.txtar
@@ -9,7 +9,8 @@
 t4: hex.Dump('foo')
 -- out/hex --
 Errors:
-error in call to encoding/hex.Decode: encoding/hex: invalid byte: U+006F 'o'
+error in call to encoding/hex.Decode: encoding/hex: invalid byte: U+006F 'o':
+    ./in.cue:5:5
 
 Result:
 t1: "666f6f"
diff --git a/pkg/encoding/json/manual.go b/pkg/encoding/json/manual.go
index 6ba9956..d5d0f9b 100644
--- a/pkg/encoding/json/manual.go
+++ b/pkg/encoding/json/manual.go
@@ -21,7 +21,9 @@
 
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/parser"
+	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
 )
 
@@ -98,7 +100,7 @@
 	expr, err := parser.ParseExpr("json", b)
 	if err != nil {
 		// NOTE: should never happen.
-		return nil, fmt.Errorf("json: could not parse JSON: %v", err)
+		return nil, errors.Wrapf(err, token.NoPos, "json: could not parse JSON")
 	}
 	return expr, nil
 }
diff --git a/pkg/encoding/json/testdata/gen.txtar b/pkg/encoding/json/testdata/gen.txtar
index 5fd43a2..2d75c33 100644
--- a/pkg/encoding/json/testdata/gen.txtar
+++ b/pkg/encoding/json/testdata/gen.txtar
@@ -18,6 +18,7 @@
 -- out/json --
 Errors:
 a: error in call to encoding/json.Validate: invalid value 10 (out of bound <3):
+    ./in.cue:4:5
     ./in.cue:4:36
     json.Validate:1:6
 
diff --git a/pkg/encoding/yaml/testdata/gen.txtar b/pkg/encoding/yaml/testdata/gen.txtar
index 1cc0baf..5c6ed9d 100644
--- a/pkg/encoding/yaml/testdata/gen.txtar
+++ b/pkg/encoding/yaml/testdata/gen.txtar
@@ -14,11 +14,14 @@
 t9: yaml.MarshalStream([{a: 1}, {b: int | *2}])
 -- out/yaml --
 Errors:
-b: error in call to encoding/yaml.Validate: incomplete value int
 a: error in call to encoding/yaml.Validate: invalid value 4 (out of bound <3):
+    ./in.cue:3:5
     ./in.cue:3:41
     yaml.Validate:3:5
+b: error in call to encoding/yaml.Validate: incomplete value int:
+    ./in.cue:5:5
 a: error in call to encoding/yaml.ValidatePartial: invalid value 4 (out of bound <3):
+    ./in.cue:6:5
     ./in.cue:6:48
     yaml.ValidatePartial:3:5
 
diff --git a/pkg/internal/builtin.go b/pkg/internal/builtin.go
index 13a034e..5bab5f3 100644
--- a/pkg/internal/builtin.go
+++ b/pkg/internal/builtin.go
@@ -20,7 +20,6 @@
 
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/parser"
-	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/compile"
@@ -126,7 +125,6 @@
 	x.Func = func(ctx *adt.OpContext, args []adt.Value) (ret adt.Expr) {
 		// call, _ := ctx.Source().(*ast.CallExpr)
 		c := &CallCtxt{
-			// src:  call,
 			ctx:     ctx,
 			args:    args,
 			builtin: b,
@@ -181,17 +179,6 @@
 
 }
 
-func pos(n adt.Node) (p token.Pos) {
-	if n == nil {
-		return
-	}
-	src := n.Source()
-	if src == nil {
-		return
-	}
-	return src.Pos()
-}
-
 func (x *Builtin) name(ctx *adt.OpContext) string {
 	if x.Pkg == 0 {
 		return x.Name
diff --git a/pkg/internal/context.go b/pkg/internal/context.go
index e08a152..9aa29ae 100644
--- a/pkg/internal/context.go
+++ b/pkg/internal/context.go
@@ -26,7 +26,6 @@
 
 // CallCtxt is passed to builtin implementations that need to use a cue.Value. This is an internal type. It's interface may change.
 type CallCtxt struct {
-	src     adt.Expr
 	ctx     *adt.OpContext
 	builtin *Builtin
 	Err     interface{}
@@ -53,7 +52,7 @@
 	// TODO: remove default
 	// v, _ = v.Default()
 	if !v.IsConcrete() {
-		c.errcf(c.src, adt.IncompleteError, "non-concrete argument %d", i)
+		c.errcf(adt.IncompleteError, "non-concrete argument %d", i)
 	}
 	return v
 }
@@ -84,7 +83,7 @@
 		return 0
 	}
 	if n.BitLen() > bits {
-		c.errf(c.src, err, "int %s overflows %s in argument %d in call to %s",
+		c.errf(err, "int %s overflows %s in argument %d in call to %s",
 			n, typ, i, c.Name())
 	}
 	res, _ := x.Int64()
@@ -106,7 +105,7 @@
 		return 0
 	}
 	if n.BitLen() > bits {
-		c.errf(c.src, err, "int %s overflows %s in argument %d in call to %s",
+		c.errf(err, "int %s overflows %s in argument %d in call to %s",
 			n, typ, i, c.Name())
 	}
 	res, _ := x.Uint64()
@@ -273,13 +272,15 @@
 		default:
 			if k := w.Kind(); k&adt.NumKind == 0 {
 				err := c.ctx.NewErrf(
-					"invalid type element %d (%s) of number list argument %d", j, k, i)
+					"invalid list element %d in argument %d to call: cannot use value %s (%s) as number",
+					j, i, w, k)
 				c.Err = &callError{err}
 				return a
 			}
 
 			err := c.ctx.NewErrf(
-				"non-concrete number value for element %d of number list argument %d", j, i)
+				"non-concrete value %s for element %d of number list argument %d",
+				w, j, i)
 			err.Code = adt.IncompleteError
 			c.Err = &callError{err}
 			return nil
@@ -309,13 +310,15 @@
 		default:
 			if k := w.Kind(); k&adt.StringKind == 0 {
 				err := c.ctx.NewErrf(
-					"invalid type element %d (%s) of string list argument %d", j, k, i)
+					"invalid list element %d in argument %d to call: cannot use value %s (%s) as string",
+					j, i, w, k)
 				c.Err = &callError{err}
 				return a
 			}
 
 			err := c.ctx.NewErrf(
-				"non-concrete string value for element %d of string list argument %d", j, i)
+				"non-concrete value %s for element %d of string list argument %d",
+				w, j, i)
 			err.Code = adt.IncompleteError
 			c.Err = &callError{err}
 			return nil
diff --git a/pkg/internal/errors.go b/pkg/internal/errors.go
index 6f1b29d..077a08d 100644
--- a/pkg/internal/errors.go
+++ b/pkg/internal/errors.go
@@ -15,12 +15,9 @@
 package internal
 
 import (
-	"encoding/json"
 	"fmt"
 
 	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
 )
 
@@ -37,97 +34,64 @@
 	return fmt.Sprint(e.b)
 }
 
-func (c *CallCtxt) errf(src adt.Node, underlying error, format string, args ...interface{}) {
+func (c *CallCtxt) errf(underlying error, format string, args ...interface{}) {
 	var errs errors.Error
 	var code adt.ErrorCode
-	if err, ok := underlying.(bottomer); ok {
-		b := err.Bottom()
+	switch x := underlying.(type) {
+	case nil:
+	case bottomer:
+		b := x.Bottom()
 		errs = b.Err
 		code = b.Code
+	case errors.Error:
+		errs = x
+	case error:
+		errs = errors.Promote(x, "")
 	}
-	errs = errors.Wrapf(errs, c.ctx.Pos(), format, args...)
-	c.Err = &callError{&adt.Bottom{Code: code, Err: errs}}
+	vErr := c.ctx.NewPosf(c.Pos(), format, args...)
+	c.Err = &callError{&adt.Bottom{Code: code, Err: errors.Wrap(vErr, errs)}}
 }
 
-func (c *CallCtxt) errcf(src adt.Node, code adt.ErrorCode, format string, args ...interface{}) {
+func (c *CallCtxt) errcf(code adt.ErrorCode, format string, args ...interface{}) {
 	err := c.ctx.NewErrf(format, args...)
 	err.Code = code
 	c.Err = &callError{err}
 }
 
 func wrapCallErr(c *CallCtxt, b *adt.Bottom) *adt.Bottom {
-	pos := token.NoPos
-	if c.src != nil {
-		if src := c.src.Source(); src != nil {
-			pos = src.Pos()
-		}
-	}
 	var err errors.Error
 	for _, e := range errors.Errors(b.Err) {
 		const msg = "error in call to %s"
 		err = errors.Append(err,
-			errors.Wrapf(e, pos, msg, c.builtin.name(c.ctx)))
+			errors.Wrapf(e, c.Pos(), msg, c.builtin.name(c.ctx)))
 	}
 	return &adt.Bottom{Code: b.Code, Err: err}
 }
 
-func (c *CallCtxt) convertError(x interface{}, name string) *adt.Bottom {
-	var err errors.Error
-	switch v := x.(type) {
-	case nil:
-		return nil
-
-	case *adt.Bottom:
-		return v
-
-	case *json.MarshalerError:
-		err = errors.Promote(v, "marshal error")
-
-	case errors.Error:
-		err = v
-
-	case error:
-		if name != "" {
-			err = errors.Newf(c.Pos(), "%s: %v", name, v)
-		} else {
-			err = errors.Newf(c.Pos(), "error in call to %s: %v", c.Name(), v)
-		}
-
-	default:
-		err = errors.Newf(token.NoPos, "%s", name)
-	}
-	if err != internal.ErrIncomplete {
-		return &adt.Bottom{
-			// Wrap to preserve position information.
-			Err: errors.Wrapf(err, c.Pos(), "error in call to %s", c.Name()),
-		}
-	}
-	return &adt.Bottom{
-		Code: adt.IncompleteError,
-		Err:  errors.Newf(c.Pos(), "incomplete values in call to %s", c.Name()),
-	}
-}
-
-func (c *CallCtxt) invalidArgType(arg adt.Expr, i int, typ string, err error) {
+func (c *CallCtxt) invalidArgType(arg adt.Value, i int, typ string, err error) {
 	if ve, ok := err.(bottomer); ok && ve.Bottom().IsIncomplete() {
 		c.Err = ve
 		return
 	}
+	if b, ok := adt.Unwrap(arg).(*adt.Bottom); ok {
+		c.Err = b
+		return
+	}
 	v, ok := arg.(adt.Value)
 	// TODO: make these permanent errors if the value did not originate from
 	// a reference.
 	if !ok {
-		c.errf(c.src, nil,
-			"cannot use incomplete value %s as %s in argument %d to %s: %v",
-			c.ctx.Str(arg), typ, i, c.Name(), err)
+		c.errf(nil,
+			"cannot use incomplete value %s as %s in argument %d to %s",
+			arg, typ, i, c.Name())
 	}
 	if err != nil {
-		c.errf(c.src, err,
-			"cannot use %s (type %s) as %s in argument %d to %s: %v",
-			c.ctx.Str(arg), v.Kind(), typ, i, c.Name(), err)
-	} else {
-		c.errf(c.src, err,
+		c.errf(err,
 			"cannot use %s (type %s) as %s in argument %d to %s",
-			c.ctx.Str(arg), v.Kind(), typ, i, c.Name())
+			arg, v.Kind(), typ, i, c.Name())
+	} else {
+		c.errf(err,
+			"cannot use %s (type %s) as %s in argument %d to %s",
+			arg, v.Kind(), typ, i, c.Name())
 	}
 }
diff --git a/pkg/list/testdata/gen.txtar b/pkg/list/testdata/gen.txtar
index ef1d79f..54d3410 100644
--- a/pkg/list/testdata/gen.txtar
+++ b/pkg/list/testdata/gen.txtar
@@ -63,47 +63,56 @@
 t54: list.Sort([{a:1}, {b:2}], list.Ascending)
 -- out/list --
 Errors:
-error in call to list.Avg: empty list
-error in call to list.Drop: negative index
-error in call to list.Max: empty list
-error in call to list.Min: empty list
-error in call to list.Range: end must be greater than start when step is positive
-error in call to list.Range: end must be less than start when step is negative
-error in call to list.Range: step must be non zero
-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
-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):
-    ./in.cue:46:24
-    list:10:9
-Ascending.x: error in call to list.Sort: conflicting values string and {b:2} (mismatched types string and struct):
-    ./in.cue:60:24
-    list:10:18
-Ascending.y: error in call to list.Sort: 2 errors in empty disjunction:
-Ascending.y: error in call to list.Sort: conflicting values number and {a:1} (mismatched types number and struct):
-    ./in.cue:60:17
-    list:10:9
-Ascending.y: error in call to list.Sort: conflicting values string and {a:1} (mismatched types string and struct):
-    ./in.cue:46:17
-    list:10:18
+error in call to list.Avg: empty list:
+    ./in.cue:4:5
 t3: cannot use "foo" (type string) as list in argument 1 to list.Avg:
     ./in.cue:5:14
+error in call to list.Drop: negative index:
+    ./in.cue:9:5
 error in call to list.FlattenN: cannot use value "foo" (type string) as list:
+    ./in.cue:15:6
     ./in.cue:15:20
 t14: cannot use "foo" (type string) as int in argument 2 to list.FlattenN:
     ./in.cue:16:24
+error in call to list.Max: empty list:
+    ./in.cue:18:6
 t17: cannot use "foo" (type string) as list in argument 1 to list.Max:
     ./in.cue:19:15
+error in call to list.Min: empty list:
+    ./in.cue:21:6
 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:
+error in call to list.Range: step must be non zero:
+    ./in.cue:26:6
+error in call to list.Range: end must be greater than start when step is positive:
+    ./in.cue:27:6
+error in call to list.Range: end must be less than start when step is negative:
+    ./in.cue:28:6
+error in call to list.Slice: negative index:
+    ./in.cue:35:6
+error in call to list.Slice: invalid index: 3 > 1:
+    ./in.cue:36:6
+error in call to list.Slice: slice bounds out of range:
+    ./in.cue:37:6
+error in call to list.Slice: slice bounds out of range:
+    ./in.cue:38:6
+Ascending.x: error in call to list.Sort: 2 errors in empty disjunction::
+    ./in.cue:46:6
+Ascending.y: error in call to list.Sort: 2 errors in empty disjunction::
+    ./in.cue:46:6
+t42: invalid list element 0 in argument 0 to call: cannot use value 1 (int) as string:
     ./in.cue:48:6
+    ./in.cue:48:24
 t45: cannot use "foo" (type string) as list in argument 1 to list.Sum:
     ./in.cue:51:15
+error in call to list.Take: negative index:
+    ./in.cue:55:6
+Ascending.x: error in call to list.Sort: 2 errors in empty disjunction::
+    ./in.cue:60:6
+Ascending.y: error in call to list.Sort: 2 errors in empty disjunction::
+    ./in.cue:60:6
 
 Result:
 t1: 2.5
@@ -156,7 +165,7 @@
 }]
 t40: _|_ // error in call to list.Sort: Ascending.x: 2 errors in empty disjunction: (and 5 more errors)
 t41: ["a", "b"]
-t42: _|_ // t42: invalid type element 0 (int) of string list argument 0
+t42: _|_ // t42: invalid list element 0 in argument 0 to call: cannot use value 1 (int) as string
 t43: 10
 t44: 0
 t45: _|_ // t45: cannot use "foo" (type string) as list in argument 1 to list.Sum
diff --git a/pkg/list/testdata/list.txtar b/pkg/list/testdata/list.txtar
index e42e16c..b4ff870 100644
--- a/pkg/list/testdata/list.txtar
+++ b/pkg/list/testdata/list.txtar
@@ -43,11 +43,13 @@
 }
 -- out/list --
 Errors:
-error in call to list.Repeat: negative count
+error in call to list.Repeat: negative count:
+    ./in.cue:4:33
+error in call to list.Concat: cannot use value 1 (type int) as list:
+    ./in.cue:19:25
+    ./in.cue:31:13
 concat.t7.v: cannot use 1 (type int) as list in argument 1 to list.Concat:
     ./in.cue:30:12
-error in call to list.Concat: cannot use value 1 (type int) as list:
-    ./in.cue:31:13
 
 Result:
 repeat: {
diff --git a/pkg/math/testdata/gen.txtar b/pkg/math/testdata/gen.txtar
index bb22999..168463c 100644
--- a/pkg/math/testdata/gen.txtar
+++ b/pkg/math/testdata/gen.txtar
@@ -29,8 +29,9 @@
     ./in.cue:5:5
 error in call to math.Jacobi: big: invalid 2nd argument to Int.Jacobi: need odd integer but got 2000:
     ./in.cue:6:5
-cannot use 2.0E+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up:
+t8: cannot use 2.0E+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up:
     ./in.cue:8:5
+    ./in.cue:8:15
 
 Result:
 t1:  3.14159265358979323846264338327950288419716939937510582097494459
@@ -38,7 +39,7 @@
 t3:  _|_ // t3: cannot call non-function math.Pi (type float)
 t6:  _|_ // error in call to math.Jacobi: big: invalid 2nd argument to Int.Jacobi: need odd integer but got 2000
 t7:  1
-t8:  _|_ // cannot use 2.0E+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up
+t8:  _|_ // t8: cannot use 2.0E+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up
 t16: 4096
 t17: 1e+4
 t18: true
diff --git a/pkg/math/testdata/round.txtar b/pkg/math/testdata/round.txtar
index adbdd8c..4b332f7 100644
--- a/pkg/math/testdata/round.txtar
+++ b/pkg/math/testdata/round.txtar
@@ -34,7 +34,8 @@
 
 -- out/math --
 Errors:
-error in call to math.MultipleOf: division by zero
+error in call to math.MultipleOf: division by zero:
+    ./in.cue:6:7
 floorE1: too many arguments in call to math.Floor (have 2, want 1):
     ./in.cue:17:10
 floorE2: cannot use "foo" (type string) as number in argument 1 to math.Floor:
diff --git a/pkg/net/testdata/gen.txtar b/pkg/net/testdata/gen.txtar
index 4b41fdb..1963604 100644
--- a/pkg/net/testdata/gen.txtar
+++ b/pkg/net/testdata/gen.txtar
@@ -22,9 +22,10 @@
 t17: net.ToIP16("127.0.0.1")
 -- out/net --
 Errors:
-error in call to net.JoinHostPort: invalid host [192, 30, 4]
 t9: invalid value "23.23.23.2333" (does not satisfy net.IPv4):
     ./in.cue:11:16
+error in call to net.JoinHostPort: invalid host [192, 30, 4]:
+    ./in.cue:9:5
 t13: invalid value "ff02::1:3" (does not satisfy net.IPv4):
     ./in.cue:15:6
     ./in.cue:15:19
diff --git a/pkg/path/testdata/error.txtar b/pkg/path/testdata/error.txtar
index cfce2fa..caee6ec 100644
--- a/pkg/path/testdata/error.txtar
+++ b/pkg/path/testdata/error.txtar
@@ -19,12 +19,10 @@
 joinErr: path.Join(["a", "b"], "foo")
 -- out/path --
 Errors:
-cannot use _|_(2 errors in empty disjunction: (and 2 more errors)) (type _|_) as string in argument 1 to path.Join: 2 errors in empty disjunction: (and 2 more errors):
-    ./in.cue:4:10
 joinErr: cannot use "foo" as *"unix" | "windows" | "plan9" | "aix" | "android" | "darwin" | "dragonfly" | "freebsd" | "hurd" | "illumos" | "ios" | "js" | "linux" | "nacl" | "netbsd" | "openbsd" | "solaris" | "zos" in argument 2 to path.Join:
     ./in.cue:4:32
 
 Result:
 joinOK:  "a/b"
-joinErr: _|_ // joinErr: cannot use "foo" as *"unix" | "windows" | "plan9" | "aix" | "android" | "darwin" | "dragonfly" | "freebsd" | "hurd" | "illumos" | "ios" | "js" | "linux" | "nacl" | "netbsd" | "openbsd" | "solaris" | "zos" in argument 2 to path.Join (and 1 more errors)
+joinErr: _|_ // joinErr: cannot use "foo" as *"unix" | "windows" | "plan9" | "aix" | "android" | "darwin" | "dragonfly" | "freebsd" | "hurd" | "illumos" | "ios" | "js" | "linux" | "nacl" | "netbsd" | "openbsd" | "solaris" | "zos" in argument 2 to path.Join
 
diff --git a/pkg/regexp/testdata/gen.txtar b/pkg/regexp/testdata/gen.txtar
index a34e36c..d11e215 100644
--- a/pkg/regexp/testdata/gen.txtar
+++ b/pkg/regexp/testdata/gen.txtar
@@ -19,12 +19,16 @@
 t14: regexp.Valid & "invalid)"
 -- out/regexp --
 Errors:
-error in call to regexp.Find: no match
-error in call to regexp.FindAll: no match
-error in call to regexp.FindAllNamedSubmatch: no match
-error in call to regexp.FindAllSubmatch: no match
 t14: invalid value "invalid)" (does not satisfy regexp.Valid): error in call to regexp.Valid: error parsing regexp: unexpected ): `invalid)`:
     ./in.cue:16:21
+error in call to regexp.Find: no match:
+    ./in.cue:4:5
+error in call to regexp.FindAll: no match:
+    ./in.cue:7:5
+error in call to regexp.FindAllSubmatch: no match:
+    ./in.cue:10:5
+error in call to regexp.FindAllNamedSubmatch: no match:
+    ./in.cue:14:6
 
 Result:
 t1: "foo"
diff --git a/pkg/strconv/testdata/gen.txtar b/pkg/strconv/testdata/gen.txtar
index 5deb5c7..443f804 100644
--- a/pkg/strconv/testdata/gen.txtar
+++ b/pkg/strconv/testdata/gen.txtar
@@ -10,17 +10,18 @@
 t5: strconv.FormatBool(true)
 -- out/strconv --
 Errors:
-int 300 overflows byte in argument 1 in call to strconv.FormatFloat:
+t2: int 300 overflows byte in argument 1 in call to strconv.FormatFloat:
     ./in.cue:4:5
-cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat:
+t3: cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat:
     ./in.cue:5:5
+    ./in.cue:5:31
 t4: cannot use 1.0 (type float) as int in argument 2 to strconv.FormatFloat:
     ./in.cue:6:31
 
 Result:
 t1: "40"
-t2: _|_ // int 300 overflows byte in argument 1 in call to strconv.FormatFloat
-t3: _|_ // cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat
+t2: _|_ // t2: int 300 overflows byte in argument 1 in call to strconv.FormatFloat
+t3: _|_ // t3: cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat
 t4: _|_ // t4: cannot use 1.0 (type float) as int in argument 2 to strconv.FormatFloat
 t5: "true"
 
diff --git a/pkg/strings/testdata/gen.txtar b/pkg/strings/testdata/gen.txtar
index eb98510..1609559 100644
--- a/pkg/strings/testdata/gen.txtar
+++ b/pkg/strings/testdata/gen.txtar
@@ -22,8 +22,9 @@
 t17: strings.MinRunes(10) & "hello"
 -- out/strings --
 Errors:
-t2: invalid type element 0 (int) of string list argument 0:
+t2: invalid list element 0 in argument 0 to call: cannot use value 1 (int) as string:
     ./in.cue:4:5
+    ./in.cue:4:19
 t10: invalid value "quux" (does not satisfy strings.MaxRunes(3)):
     ./in.cue:12:6
     ./in.cue:12:23
@@ -43,7 +44,7 @@
 
 Result:
 t1: "Hello World!"
-t2: _|_ // t2: invalid type element 0 (int) of string list argument 0
+t2: _|_ // t2: invalid list element 0 in argument 0 to call: cannot use value 1 (int) as string
 t3: 97
 t4: 'llo'
 t5: "✓ H"