mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
go/types, types2: better error messages for invalid calls
Rather than reporting "non-function" for an invalid type parameter, report which type in the type parameter's type set is not a function. Change-Id: I8beec25cc337bae8e03d23e62d97aa82db46bab4 Reviewed-on: https://go-review.googlesource.com/c/go/+/654475 Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Robert Findley <rfindley@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
8b7e376e71
commit
584e631023
@ -244,19 +244,19 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
|
|||||||
|
|
||||||
// If the operand type is a type parameter, all types in its type set
|
// If the operand type is a type parameter, all types in its type set
|
||||||
// must have a common underlying type, which must be a signature.
|
// must have a common underlying type, which must be a signature.
|
||||||
// TODO(gri) use commonUnder condition for better error message
|
u, err := commonUnder(x.typ, func(t, u Type) *errorCause {
|
||||||
u, err := commonUnder(x.typ, nil)
|
if _, ok := u.(*Signature); u != nil && !ok {
|
||||||
sig, _ := u.(*Signature)
|
return newErrorCause("%s is not a function", t)
|
||||||
if sig == nil {
|
|
||||||
if err != nil {
|
|
||||||
check.errorf(x, InvalidCall, invalidOp+"cannot call %s: %s", x, err.format(check))
|
|
||||||
} else {
|
|
||||||
check.errorf(x, InvalidCall, invalidOp+"cannot call non-function %s", x)
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
check.errorf(x, InvalidCall, invalidOp+"cannot call %s: %s", x, err.format(check))
|
||||||
x.mode = invalid
|
x.mode = invalid
|
||||||
x.expr = call
|
x.expr = call
|
||||||
return statement
|
return statement
|
||||||
}
|
}
|
||||||
|
sig := u.(*Signature) // u must be a signature per the commonUnder condition
|
||||||
|
|
||||||
// Capture wasGeneric before sig is potentially instantiated below.
|
// Capture wasGeneric before sig is potentially instantiated below.
|
||||||
wasGeneric := sig.TypeParams().Len() > 0
|
wasGeneric := sig.TypeParams().Len() > 0
|
||||||
|
@ -246,19 +246,19 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
|
|||||||
|
|
||||||
// If the operand type is a type parameter, all types in its type set
|
// If the operand type is a type parameter, all types in its type set
|
||||||
// must have a common underlying type, which must be a signature.
|
// must have a common underlying type, which must be a signature.
|
||||||
// TODO(gri) use commonUnder condition for better error message
|
u, err := commonUnder(x.typ, func(t, u Type) *errorCause {
|
||||||
u, err := commonUnder(x.typ, nil)
|
if _, ok := u.(*Signature); u != nil && !ok {
|
||||||
sig, _ := u.(*Signature)
|
return newErrorCause("%s is not a function", t)
|
||||||
if sig == nil {
|
|
||||||
if err != nil {
|
|
||||||
check.errorf(x, InvalidCall, invalidOp+"cannot call %s: %s", x, err.format(check))
|
|
||||||
} else {
|
|
||||||
check.errorf(x, InvalidCall, invalidOp+"cannot call non-function %s", x)
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
check.errorf(x, InvalidCall, invalidOp+"cannot call %s: %s", x, err.format(check))
|
||||||
x.mode = invalid
|
x.mode = invalid
|
||||||
x.expr = call
|
x.expr = call
|
||||||
return statement
|
return statement
|
||||||
}
|
}
|
||||||
|
sig := u.(*Signature) // u must be a signature per the commonUnder condition
|
||||||
|
|
||||||
// Capture wasGeneric before sig is potentially instantiated below.
|
// Capture wasGeneric before sig is potentially instantiated below.
|
||||||
wasGeneric := sig.TypeParams().Len() > 0
|
wasGeneric := sig.TypeParams().Len() > 0
|
||||||
|
8
src/internal/types/testdata/check/lookup1.go
vendored
8
src/internal/types/testdata/check/lookup1.go
vendored
@ -11,7 +11,7 @@ func _() {
|
|||||||
x, aBc int
|
x, aBc int
|
||||||
}
|
}
|
||||||
_ = s.x
|
_ = s.x
|
||||||
_ = s /* ERROR "invalid operation: cannot call non-function s.x (variable of type int)" */ .x()
|
_ = s /* ERROR "invalid operation: cannot call s.x (variable of type int): int is not a function" */ .x()
|
||||||
_ = s.X // ERROR "s.X undefined (type struct{x int; aBc int} has no field or method X, but does have field x)"
|
_ = s.X // ERROR "s.X undefined (type struct{x int; aBc int} has no field or method X, but does have field x)"
|
||||||
_ = s.X /* ERROR "s.X undefined (type struct{x int; aBc int} has no field or method X, but does have field x)" */ ()
|
_ = s.X /* ERROR "s.X undefined (type struct{x int; aBc int} has no field or method X, but does have field x)" */ ()
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ func _() {
|
|||||||
}
|
}
|
||||||
var s S
|
var s S
|
||||||
_ = s.x
|
_ = s.x
|
||||||
_ = s /* ERROR "invalid operation: cannot call non-function s.x (variable of type int)" */ .x()
|
_ = s /* ERROR "invalid operation: cannot call s.x (variable of type int): int is not a function" */ .x()
|
||||||
_ = s.X // ERROR "s.X undefined (type S has no field or method X, but does have field x)"
|
_ = s.X // ERROR "s.X undefined (type S has no field or method X, but does have field x)"
|
||||||
_ = s.X /* ERROR "s.X undefined (type S has no field or method X, but does have field x)" */ ()
|
_ = s.X /* ERROR "s.X undefined (type S has no field or method X, but does have field x)" */ ()
|
||||||
}
|
}
|
||||||
@ -77,9 +77,9 @@ func _[P any](x P) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func _[P int](x P) {
|
func _[P int](x P) {
|
||||||
x /* ERROR "cannot call non-function x (variable of type P constrained by int)" */ ()
|
x /* ERROR "cannot call x (variable of type P constrained by int): int is not a function" */ ()
|
||||||
}
|
}
|
||||||
|
|
||||||
func _[P int | string](x P) {
|
func _[P int | string](x P) {
|
||||||
x /* ERROR "cannot call x (variable of type P constrained by int | string): int and string have different underlying types" */ ()
|
x /* ERROR "cannot call x (variable of type P constrained by int | string): int is not a function" */ ()
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ const P = 2 // declare P to avoid noisy 'undefined' errors below.
|
|||||||
|
|
||||||
// The following parse as invalid array types due to parsing ambiguitiues.
|
// The following parse as invalid array types due to parsing ambiguitiues.
|
||||||
type _ [P *int /* ERROR "int (type) is not an expression" */ ]int
|
type _ [P *int /* ERROR "int (type) is not an expression" */ ]int
|
||||||
type _ [P /* ERROR "non-function P" */ (*int)]int
|
type _ [P /* ERROR "cannot call P (untyped int constant 2): untyped int is not a function" */ (*int)]int
|
||||||
|
|
||||||
// Adding a trailing comma or an enclosing interface resolves the ambiguity.
|
// Adding a trailing comma or an enclosing interface resolves the ambiguity.
|
||||||
type _[P *int,] int
|
type _[P *int,] int
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
const A = complex(0()) // ERROR "cannot call non-function"
|
const A = complex(0()) // ERROR "cannot call .* not a function"
|
||||||
|
@ -13,7 +13,7 @@ func F() {
|
|||||||
slice := []int{1, 2, 3}
|
slice := []int{1, 2, 3}
|
||||||
_ = slice
|
_ = slice
|
||||||
len := int(2)
|
len := int(2)
|
||||||
println(len(slice)) // ERROR "cannot call non-function len .type int., declared at LINE-1|expected function|cannot call non-function len"
|
println(len(slice)) // ERROR "cannot call non-function len .type int., declared at LINE-1|expected function|cannot call len"
|
||||||
const iota = 1
|
const iota = 1
|
||||||
println(iota(slice)) // ERROR "cannot call non-function iota .type int., declared at LINE-1|expected function|cannot call non-function iota"
|
println(iota(slice)) // ERROR "cannot call non-function iota .type int., declared at LINE-1|expected function|cannot call iota"
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ package p
|
|||||||
var a = []int{1,2,3}
|
var a = []int{1,2,3}
|
||||||
|
|
||||||
func _(len int) {
|
func _(len int) {
|
||||||
_ = len(a) // ERROR "cannot call non-function|expected function"
|
_ = len(a) // ERROR "cannot call|expected function"
|
||||||
}
|
}
|
||||||
|
|
||||||
var cap = false
|
var cap = false
|
||||||
var _ = cap(a) // ERROR "cannot call non-function|expected function"
|
var _ = cap(a) // ERROR "cannot call|expected function"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user