mirror of
https://github.com/golang/go
synced 2024-11-19 02:44:44 -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.
|
// false, and *x is undefined.
|
||||||
//
|
//
|
||||||
func (check *checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) {
|
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
|
// determine actual arguments
|
||||||
var arg getter
|
var arg getter
|
||||||
nargs := len(call.Args)
|
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:
|
case _Make, _New, _Offsetof, _Trace:
|
||||||
// arguments requires special handling
|
// arguments require 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check argument count
|
// check argument count
|
||||||
|
@ -16,12 +16,7 @@ func (check *checker) call(x *operand, e *ast.CallExpr) exprKind {
|
|||||||
|
|
||||||
switch x.mode {
|
switch x.mode {
|
||||||
case invalid:
|
case invalid:
|
||||||
// We don't have a valid call or conversion but we have a list of arguments.
|
check.use(e.Args)
|
||||||
// Typecheck them independently for better partial type information in
|
|
||||||
// the presence of type errors.
|
|
||||||
for _, arg := range e.Args {
|
|
||||||
check.expr(x, arg)
|
|
||||||
}
|
|
||||||
x.mode = invalid
|
x.mode = invalid
|
||||||
x.expr = e
|
x.expr = e
|
||||||
return statement
|
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.
|
// 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
|
// 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)
|
_ = unsafe.Offsetof(y2 /* ERROR method value */ .m)
|
||||||
|
|
||||||
var s []byte
|
var s []byte
|
||||||
_ = s
|
|
||||||
_ = unsafe.Offsetof(s... /* ERROR invalid use of \.\.\. */ )
|
_ = unsafe.Offsetof(s... /* ERROR invalid use of \.\.\. */ )
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,7 +730,6 @@ func trace1() {
|
|||||||
// _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
|
// _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
|
||||||
|
|
||||||
var s []byte
|
var s []byte
|
||||||
_ = s
|
|
||||||
trace(s... /* ERROR invalid use of \.\.\. */ )
|
trace(s... /* ERROR invalid use of \.\.\. */ )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user