aboutsummaryrefslogtreecommitdiff
path: root/src/go/types/expr.go
diff options
context:
space:
mode:
authorRob Findley <rfindley@google.com>2020-10-26 22:44:54 -0400
committerRobert Findley <rfindley@google.com>2020-11-05 20:35:00 +0000
commit2822bae168fa5d7b14c87d2b2ee22cb85fc90cce (patch)
tree7e60ef1f9cae0a3dee654b55ef012c9d49f628bb /src/go/types/expr.go
parentd508d86cf12a3c4ee139d31f5f5c9e5e53566ecc (diff)
downloadgo-2822bae168fa5d7b14c87d2b2ee22cb85fc90cce.tar.gz
go-2822bae168fa5d7b14c87d2b2ee22cb85fc90cce.zip
go/types: add unexported start and end positions to type checker errors
Tools often need to associate errors not with a single position, but with a span of source code. For example, gopls currently estimates diagnostic spans using heuristics to expand the positions reported by the type checker to surrounding source code. Unfortunately this is often inaccurate. This CL lays the groundwork to solve this within go/types by adding a start and end position to type checker errors. This is an experimental API, both because we are uncertain of the ideal representation for these spans and because their initial positioning is naive. In most cases this CL simply expands errors to the surrounding ast.Node being typechecked, if available. This might not be the best error span to present to the user. For these reasons the API is unexported -- gopls can read these positions using reflection, allowing us to gain experience and improve them during the next development cycle. For golang/go#42290 Change-Id: I39a04d70ea2bb2134b4d4c937f32b2ddb4456430 Reviewed-on: https://go-review.googlesource.com/c/go/+/265250 Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> Trust: Robert Findley <rfindley@google.com> Trust: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/go/types/expr.go')
-rw-r--r--src/go/types/expr.go126
1 files changed, 66 insertions, 60 deletions
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 5f3415a59d..1f8b946407 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -68,11 +68,11 @@ var unaryOpPredicates = opPredicates{
func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
if pred := m[op]; pred != nil {
if !pred(x.typ) {
- check.invalidOp(x.pos(), _UndefinedOp, "operator %s not defined for %s", op, x)
+ check.invalidOp(x, _UndefinedOp, "operator %s not defined for %s", op, x)
return false
}
} else {
- check.invalidAST(x.pos(), "unknown operator %s", op)
+ check.invalidAST(x, "unknown operator %s", op)
return false
}
return true
@@ -85,7 +85,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
// spec: "As an exception to the addressability
// requirement x may also be a composite literal."
if _, ok := unparen(x.expr).(*ast.CompositeLit); !ok && x.mode != variable {
- check.invalidOp(x.pos(), _UnaddressableOperand, "cannot take address of %s", x)
+ check.invalidOp(x, _UnaddressableOperand, "cannot take address of %s", x)
x.mode = invalid
return
}
@@ -96,12 +96,12 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
case token.ARROW:
typ, ok := x.typ.Underlying().(*Chan)
if !ok {
- check.invalidOp(x.pos(), _InvalidReceive, "cannot receive from non-channel %s", x)
+ check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x)
x.mode = invalid
return
}
if typ.dir == SendOnly {
- check.invalidOp(x.pos(), _InvalidReceive, "cannot receive from send-only channel %s", x)
+ check.invalidOp(x, _InvalidReceive, "cannot receive from send-only channel %s", x)
x.mode = invalid
return
}
@@ -362,7 +362,7 @@ func (check *Checker) isRepresentable(x *operand, typ *Basic) error {
msg = "cannot convert %s to %s"
code = _InvalidConstVal
}
- return check.newErrorf(x.pos(), code, msg, x, typ)
+ return check.newErrorf(x, code, false, msg, x, typ)
}
return nil
}
@@ -470,7 +470,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) {
// We already know from the shift check that it is representable
// as an integer if it is a constant.
if !isInteger(typ) {
- check.invalidOp(x.Pos(), _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ)
+ check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ)
return
}
// Even if we have an integer, if the value is a constant we
@@ -521,7 +521,7 @@ func (check *Checker) canConvertUntyped(x *operand, target Type) error {
check.updateExprType(x.expr, target, false)
}
} else if xkind != tkind {
- return check.newErrorf(x.pos(), _InvalidUntypedConversion, "cannot convert %s to %s", x, target)
+ return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target)
}
return nil
}
@@ -535,7 +535,7 @@ func (check *Checker) canConvertUntyped(x *operand, target Type) error {
} else {
newTarget := check.implicitType(x, target)
if newTarget == nil {
- return check.newErrorf(x.pos(), _InvalidUntypedConversion, "cannot convert %s to %s", x, target)
+ return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target)
}
target = newTarget
}
@@ -641,7 +641,7 @@ func (check *Checker) comparison(x, y *operand, op token.Token) {
}
if err != "" {
- check.errorf(x.pos(), code, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
+ check.errorf(x, code, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err)
x.mode = invalid
return
}
@@ -678,7 +678,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
// as an integer. Nothing to do.
} else {
// shift has no chance
- check.invalidOp(x.pos(), _InvalidShiftOperand, "shifted operand %s must be integer", x)
+ check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s must be integer", x)
x.mode = invalid
return
}
@@ -695,7 +695,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
return
}
default:
- check.invalidOp(y.pos(), _InvalidShiftCount, "shift count %s must be integer", y)
+ check.invalidOp(y, _InvalidShiftCount, "shift count %s must be integer", y)
x.mode = invalid
return
}
@@ -708,7 +708,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
yval = constant.ToInt(y.val)
assert(yval.Kind() == constant.Int)
if constant.Sign(yval) < 0 {
- check.invalidOp(y.pos(), _InvalidShiftCount, "negative shift count %s", y)
+ check.invalidOp(y, _InvalidShiftCount, "negative shift count %s", y)
x.mode = invalid
return
}
@@ -720,7 +720,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64
s, ok := constant.Uint64Val(yval)
if !ok || s > shiftBound {
- check.invalidOp(y.pos(), _InvalidShiftCount, "invalid shift count %s", y)
+ check.invalidOp(y, _InvalidShiftCount, "invalid shift count %s", y)
x.mode = invalid
return
}
@@ -777,7 +777,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
// non-constant shift - lhs must be an integer
if !isInteger(x.typ) {
- check.invalidOp(x.pos(), _InvalidShiftOperand, "shifted operand %s must be integer", x)
+ check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s must be integer", x)
x.mode = invalid
return
}
@@ -841,7 +841,11 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
// only report an error if we have valid types
// (otherwise we had an error reported elsewhere already)
if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] {
- check.invalidOp(x.pos(), _MismatchedTypes, "mismatched types %s and %s", x.typ, y.typ)
+ var posn positioner = x
+ if e != nil {
+ posn = e
+ }
+ check.invalidOp(posn, _MismatchedTypes, "mismatched types %s and %s", x.typ, y.typ)
}
x.mode = invalid
return
@@ -855,7 +859,7 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
if op == token.QUO || op == token.REM {
// check for zero divisor
if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 {
- check.invalidOp(y.pos(), _DivByZero, "division by zero")
+ check.invalidOp(&y, _DivByZero, "division by zero")
x.mode = invalid
return
}
@@ -865,7 +869,7 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
re, im := constant.Real(y.val), constant.Imag(y.val)
re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im)
if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 {
- check.invalidOp(y.pos(), _DivByZero, "division by zero")
+ check.invalidOp(&y, _DivByZero, "division by zero")
x.mode = invalid
return
}
@@ -918,7 +922,7 @@ func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
// the index must be of integer type
if !isInteger(x.typ) {
- check.invalidArg(x.pos(), _InvalidIndex, "index %s must be integer", &x)
+ check.invalidArg(&x, _InvalidIndex, "index %s must be integer", &x)
return
}
@@ -928,13 +932,13 @@ func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
// a constant index i must be in bounds
if constant.Sign(x.val) < 0 {
- check.invalidArg(x.pos(), _InvalidIndex, "index %s must not be negative", &x)
+ check.invalidArg(&x, _InvalidIndex, "index %s must not be negative", &x)
return
}
v, valid := constant.Int64Val(constant.ToInt(x.val))
if !valid || max >= 0 && v >= max {
- check.errorf(x.pos(), _InvalidIndex, "index %s is out of bounds", &x)
+ check.errorf(&x, _InvalidIndex, "index %s is out of bounds", &x)
return
}
@@ -960,12 +964,12 @@ func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64
index = i
validIndex = true
} else {
- check.errorf(e.Pos(), _InvalidLitIndex, "index %s must be integer constant", kv.Key)
+ check.errorf(e, _InvalidLitIndex, "index %s must be integer constant", kv.Key)
}
}
eval = kv.Value
} else if length >= 0 && index >= length {
- check.errorf(e.Pos(), _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
+ check.errorf(e, _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
} else {
validIndex = true
}
@@ -973,7 +977,7 @@ func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64
// if we have a valid index, check for duplicate entries
if validIndex {
if visited[index] {
- check.errorf(e.Pos(), _DuplicateLitKey, "duplicate index %d in array or slice literal", index)
+ check.errorf(e, _DuplicateLitKey, "duplicate index %d in array or slice literal", index)
}
visited[index] = true
}
@@ -1063,13 +1067,13 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case *ast.Ellipsis:
// ellipses are handled explicitly where they are legal
// (array composite literals and parameter lists)
- check.error(e.Pos(), _BadDotDotDotSyntax, "invalid use of '...'")
+ check.error(e, _BadDotDotDotSyntax, "invalid use of '...'")
goto Error
case *ast.BasicLit:
x.setConst(e.Kind, e.Value)
if x.mode == invalid {
- check.invalidAST(e.Pos(), "invalid literal %v", e.Value)
+ check.invalidAST(e, "invalid literal %v", e.Value)
goto Error
}
@@ -1090,7 +1094,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
x.mode = value
x.typ = sig
} else {
- check.invalidAST(e.Pos(), "invalid function literal %s", e)
+ check.invalidAST(e, "invalid function literal %s", e)
goto Error
}
@@ -1122,7 +1126,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
default:
// TODO(gri) provide better error messages depending on context
- check.error(e.Pos(), _UntypedLit, "missing type in composite literal")
+ check.error(e, _UntypedLit, "missing type in composite literal")
goto Error
}
@@ -1138,7 +1142,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
for _, e := range e.Elts {
kv, _ := e.(*ast.KeyValueExpr)
if kv == nil {
- check.error(e.Pos(), _MixedStructLit, "mixture of field:value and value elements in struct literal")
+ check.error(e, _MixedStructLit, "mixture of field:value and value elements in struct literal")
continue
}
key, _ := kv.Key.(*ast.Ident)
@@ -1146,12 +1150,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
// so we don't drop information on the floor
check.expr(x, kv.Value)
if key == nil {
- check.errorf(kv.Pos(), _InvalidLitField, "invalid field name %s in struct literal", kv.Key)
+ check.errorf(kv, _InvalidLitField, "invalid field name %s in struct literal", kv.Key)
continue
}
i := fieldIndex(utyp.fields, check.pkg, key.Name)
if i < 0 {
- check.errorf(kv.Pos(), _MissingLitField, "unknown field %s in struct literal", key.Name)
+ check.errorf(kv, _MissingLitField, "unknown field %s in struct literal", key.Name)
continue
}
fld := fields[i]
@@ -1160,7 +1164,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
check.assignment(x, etyp, "struct literal")
// 0 <= i < len(fields)
if visited[i] {
- check.errorf(kv.Pos(), _DuplicateLitField, "duplicate field name %s in struct literal", key.Name)
+ check.errorf(kv, _DuplicateLitField, "duplicate field name %s in struct literal", key.Name)
continue
}
visited[i] = true
@@ -1169,25 +1173,27 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
// no element must have a key
for i, e := range e.Elts {
if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
- check.error(kv.Pos(), _MixedStructLit, "mixture of field:value and value elements in struct literal")
+ check.error(kv, _MixedStructLit, "mixture of field:value and value elements in struct literal")
continue
}
check.expr(x, e)
if i >= len(fields) {
- check.error(x.pos(), _InvalidStructLit, "too many values in struct literal")
+ check.error(x, _InvalidStructLit, "too many values in struct literal")
break // cannot continue
}
// i < len(fields)
fld := fields[i]
if !fld.Exported() && fld.pkg != check.pkg {
- check.errorf(x.pos(), _UnexportedLitField, "implicit assignment to unexported field %s in %s literal", fld.name, typ)
+ check.errorf(x,
+ _UnexportedLitField,
+ "implicit assignment to unexported field %s in %s literal", fld.name, typ)
continue
}
etyp := fld.typ
check.assignment(x, etyp, "struct literal")
}
if len(e.Elts) < len(fields) {
- check.error(e.Rbrace, _InvalidStructLit, "too few values in struct literal")
+ check.error(inNode(e, e.Rbrace), _InvalidStructLit, "too few values in struct literal")
// ok to continue
}
}
@@ -1197,7 +1203,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
// This is a stop-gap solution. Should use Checker.objPath to report entire
// path starting with earliest declaration in the source. TODO(gri) fix this.
if utyp.elem == nil {
- check.error(e.Pos(), _InvalidTypeCycle, "illegal cycle in type declaration")
+ check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration")
goto Error
}
n := check.indexedElts(e.Elts, utyp.elem, utyp.len)
@@ -1224,7 +1230,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
// Prevent crash if the slice referred to is not yet set up.
// See analogous comment for *Array.
if utyp.elem == nil {
- check.error(e.Pos(), _InvalidTypeCycle, "illegal cycle in type declaration")
+ check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration")
goto Error
}
check.indexedElts(e.Elts, utyp.elem, -1)
@@ -1233,14 +1239,14 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
// Prevent crash if the map referred to is not yet set up.
// See analogous comment for *Array.
if utyp.key == nil || utyp.elem == nil {
- check.error(e.Pos(), _InvalidTypeCycle, "illegal cycle in type declaration")
+ check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration")
goto Error
}
visited := make(map[interface{}][]Type, len(e.Elts))
for _, e := range e.Elts {
kv, _ := e.(*ast.KeyValueExpr)
if kv == nil {
- check.error(e.Pos(), _MissingLitKey, "missing key in map literal")
+ check.error(e, _MissingLitKey, "missing key in map literal")
continue
}
check.exprWithHint(x, kv.Key, utyp.key)
@@ -1265,7 +1271,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
visited[xkey] = nil
}
if duplicate {
- check.errorf(x.pos(), _DuplicateLitKey, "duplicate key %s in map literal", x.val)
+ check.errorf(x, _DuplicateLitKey, "duplicate key %s in map literal", x.val)
continue
}
}
@@ -1287,7 +1293,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
}
// if utyp is invalid, an error was reported before
if utyp != Typ[Invalid] {
- check.errorf(e.Pos(), _InvalidLit, "invalid composite literal type %s", typ)
+ check.errorf(e, _InvalidLit, "invalid composite literal type %s", typ)
goto Error
}
}
@@ -1361,12 +1367,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
}
if !valid {
- check.invalidOp(x.pos(), _NonIndexableOperand, "cannot index %s", x)
+ check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x)
goto Error
}
if e.Index == nil {
- check.invalidAST(e.Pos(), "missing index for %s", x)
+ check.invalidAST(e, "missing index for %s", x)
goto Error
}
@@ -1386,7 +1392,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case *Basic:
if isString(typ) {
if e.Slice3 {
- check.invalidOp(x.pos(), _InvalidSliceExpr, "3-index slice of string")
+ check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string")
goto Error
}
valid = true
@@ -1404,7 +1410,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
valid = true
length = typ.len
if x.mode != variable {
- check.invalidOp(x.pos(), _NonSliceableOperand, "cannot slice %s (value not addressable)", x)
+ check.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", x)
goto Error
}
x.typ = &Slice{elem: typ.elem}
@@ -1422,7 +1428,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
}
if !valid {
- check.invalidOp(x.pos(), _NonSliceableOperand, "cannot slice %s", x)
+ check.invalidOp(x, _NonSliceableOperand, "cannot slice %s", x)
goto Error
}
@@ -1430,7 +1436,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
// spec: "Only the first index may be omitted; it defaults to 0."
if e.Slice3 && (e.High == nil || e.Max == nil) {
- check.invalidAST(e.Rbrack, "2nd and 3rd index required in 3-index slice")
+ check.invalidAST(inNode(e, e.Rbrack), "2nd and 3rd index required in 3-index slice")
goto Error
}
@@ -1467,7 +1473,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
if x > 0 {
for _, y := range ind[i+1:] {
if y >= 0 && x > y {
- check.errorf(e.Rbrack, _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y)
+ check.errorf(inNode(e, e.Rbrack), _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y)
break L // only report one error, ok to continue
}
}
@@ -1481,21 +1487,21 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
}
xtyp, _ := x.typ.Underlying().(*Interface)
if xtyp == nil {
- check.invalidOp(x.pos(), _InvalidAssert, "%s is not an interface", x)
+ check.invalidOp(x, _InvalidAssert, "%s is not an interface", x)
goto Error
}
// x.(type) expressions are handled explicitly in type switches
if e.Type == nil {
// Don't use invalidAST because this can occur in the AST produced by
// go/parser.
- check.error(e.Pos(), _BadTypeKeyword, "use of .(type) outside type switch")
+ check.error(e, _BadTypeKeyword, "use of .(type) outside type switch")
goto Error
}
T := check.typ(e.Type)
if T == Typ[Invalid] {
goto Error
}
- check.typeAssertion(x.pos(), x, xtyp, T)
+ check.typeAssertion(x, x, xtyp, T)
x.mode = commaok
x.typ = T
@@ -1514,7 +1520,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
x.mode = variable
x.typ = typ.base
} else {
- check.invalidOp(x.pos(), _InvalidIndirection, "cannot indirect %s", x)
+ check.invalidOp(x, _InvalidIndirection, "cannot indirect %s", x)
goto Error
}
}
@@ -1541,7 +1547,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case *ast.KeyValueExpr:
// key:value expressions are handled in composite literals
- check.invalidAST(e.Pos(), "no key:value expected")
+ check.invalidAST(e, "no key:value expected")
goto Error
case *ast.ArrayType, *ast.StructType, *ast.FuncType,
@@ -1593,7 +1599,7 @@ func keyVal(x constant.Value) interface{} {
}
// typeAssertion checks that x.(T) is legal; xtyp must be the type of x.
-func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, T Type) {
+func (check *Checker) typeAssertion(at positioner, x *operand, xtyp *Interface, T Type) {
method, wrongType := check.assertableTo(xtyp, T)
if method == nil {
return
@@ -1608,7 +1614,7 @@ func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface,
} else {
msg = "missing method " + method.name
}
- check.errorf(pos, _ImpossibleAssert, "%s cannot have dynamic type %s (%s)", x, T, msg)
+ check.errorf(at, _ImpossibleAssert, "%s cannot have dynamic type %s (%s)", x, T, msg)
}
func (check *Checker) singleValue(x *operand) {
@@ -1616,7 +1622,7 @@ func (check *Checker) singleValue(x *operand) {
// tuple types are never named - no need for underlying type below
if t, ok := x.typ.(*Tuple); ok {
assert(t.Len() != 1)
- check.errorf(x.pos(), _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x)
+ check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x)
x.mode = invalid
}
}
@@ -1649,7 +1655,7 @@ func (check *Checker) multiExpr(x *operand, e ast.Expr) {
msg = "%s is not an expression"
code = _NotAnExpr
}
- check.errorf(x.pos(), code, msg, x)
+ check.errorf(x, code, msg, x)
x.mode = invalid
}
@@ -1676,7 +1682,7 @@ func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
msg = "%s is not an expression"
code = _NotAnExpr
}
- check.errorf(x.pos(), code, msg, x)
+ check.errorf(x, code, msg, x)
x.mode = invalid
}
@@ -1687,7 +1693,7 @@ func (check *Checker) exprOrType(x *operand, e ast.Expr) {
check.rawExpr(x, e, nil)
check.singleValue(x)
if x.mode == novalue {
- check.errorf(x.pos(), _NotAnExpr, "%s used as value or type", x)
+ check.errorf(x, _NotAnExpr, "%s used as value or type", x)
x.mode = invalid
}
}