mirror of
https://github.com/golang/go
synced 2024-11-19 00:54:42 -07:00
go.tools/go/types: more robust handling of ... errors with built-ins
Catch ... errors earlier and in case of error, type-check all arguments anyway for better type reporting and fewer "declared but not used" errors. R=adonovan CC=golang-dev https://golang.org/cl/14600043
This commit is contained in:
parent
f54303d6cb
commit
579c61d653
@ -19,6 +19,14 @@ import (
|
||||
// false, and *x is undefined.
|
||||
//
|
||||
func (check *checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) {
|
||||
// append is the only built-in that permits the use of ... for the last argument
|
||||
bin := predeclaredFuncs[id]
|
||||
if call.Ellipsis.IsValid() && id != _Append {
|
||||
check.invalidOp(call.Ellipsis, "invalid use of ... with built-in %s", bin.name)
|
||||
check.use(call.Args)
|
||||
return
|
||||
}
|
||||
|
||||
// determine actual arguments
|
||||
var arg getter
|
||||
nargs := len(call.Args)
|
||||
@ -34,14 +42,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||
}
|
||||
}
|
||||
case _Make, _New, _Offsetof, _Trace:
|
||||
// arguments requires special handling
|
||||
}
|
||||
|
||||
// append is the only built-in that permits the use of ... for the last argument
|
||||
bin := predeclaredFuncs[id]
|
||||
if call.Ellipsis.IsValid() && id != _Append {
|
||||
check.invalidOp(call.Ellipsis, "invalid use of ... with built-in %s", bin.name)
|
||||
return
|
||||
// arguments require special handling
|
||||
}
|
||||
|
||||
// check argument count
|
||||
|
@ -16,12 +16,7 @@ func (check *checker) call(x *operand, e *ast.CallExpr) exprKind {
|
||||
|
||||
switch x.mode {
|
||||
case invalid:
|
||||
// We don't have a valid call or conversion but we have a list of arguments.
|
||||
// Typecheck them independently for better partial type information in
|
||||
// the presence of type errors.
|
||||
for _, arg := range e.Args {
|
||||
check.expr(x, arg)
|
||||
}
|
||||
check.use(e.Args)
|
||||
x.mode = invalid
|
||||
x.expr = e
|
||||
return statement
|
||||
@ -85,6 +80,16 @@ func (check *checker) call(x *operand, e *ast.CallExpr) exprKind {
|
||||
}
|
||||
}
|
||||
|
||||
// use type-checks each list element.
|
||||
// Useful to make sure a list of expressions is evaluated
|
||||
// (and variables are "used") in the presence of other errors.
|
||||
func (check *checker) use(list []ast.Expr) {
|
||||
var x operand
|
||||
for _, e := range list {
|
||||
check.rawExpr(&x, e, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gri) use unpack for assignment checking as well.
|
||||
|
||||
// A getter sets x as the i'th operand, where 0 <= i < n and n is the total
|
||||
|
2
go/types/testdata/builtins.src
vendored
2
go/types/testdata/builtins.src
vendored
@ -629,7 +629,6 @@ func Offsetof1() {
|
||||
_ = unsafe.Offsetof(y2 /* ERROR method value */ .m)
|
||||
|
||||
var s []byte
|
||||
_ = s
|
||||
_ = unsafe.Offsetof(s... /* ERROR invalid use of \.\.\. */ )
|
||||
}
|
||||
|
||||
@ -731,7 +730,6 @@ func trace1() {
|
||||
// _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
|
||||
|
||||
var s []byte
|
||||
_ = s
|
||||
trace(s... /* ERROR invalid use of \.\.\. */ )
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user