Otherwise, the error can be confusing if one forgets or doesn't know
that the builtin is being shadowed, which is not common practice.
Fixes #22822.
Change-Id: I735393b5ce28cb83815a1c3f7cd2e7bb5080a32d
Reviewed-on: https://go-review.googlesource.com/97455
Reviewed-by: Robert Griesemer <gri@golang.org>
default:
n.Op = OCALLFUNC
if t.Etype != TFUNC {
- yyerror("cannot call non-function %v (type %v)", l, t)
+ name := l.String()
+ if isBuiltinFuncName(name) {
+ // be more specific when the function
+ // name matches a predeclared function
+ yyerror("cannot call non-function %s (type %v), declared at %s",
+ name, t, linestr(l.Name.Defn.Pos))
+ } else {
+ yyerror("cannot call non-function %s (type %v)", name, t)
+ }
n.Type = nil
return n
}
{"recover", ORECOVER},
}
+// isBuiltinFuncName reports whether name matches a builtin function
+// name.
+func isBuiltinFuncName(name string) bool {
+ for _, fn := range builtinFuncs {
+ if fn.name == name {
+ return true
+ }
+ }
+ return false
+}
+
var unsafeFuncs = [...]struct {
name string
op Op
--- /dev/null
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that calling a function shadowing a built-in provides a good
+// error message.
+
+package main
+
+func F() {
+ slice := []int{1, 2, 3}
+ len := int(2)
+ println(len(slice)) // ERROR "cannot call non-function len .type int., declared at"
+}