Skip to content

Commit 1e308fb

Browse files
committed
cmd/compile: improved error message when calling a shadowed builtin
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 <[email protected]>
1 parent 4b1d704 commit 1e308fb

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

src/cmd/compile/internal/gc/typecheck.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,15 @@ func typecheck1(n *Node, top int) *Node {
12501250
default:
12511251
n.Op = OCALLFUNC
12521252
if t.Etype != TFUNC {
1253-
yyerror("cannot call non-function %v (type %v)", l, t)
1253+
name := l.String()
1254+
if isBuiltinFuncName(name) {
1255+
// be more specific when the function
1256+
// name matches a predeclared function
1257+
yyerror("cannot call non-function %s (type %v), declared at %s",
1258+
name, t, linestr(l.Name.Defn.Pos))
1259+
} else {
1260+
yyerror("cannot call non-function %s (type %v)", name, t)
1261+
}
12541262
n.Type = nil
12551263
return n
12561264
}

src/cmd/compile/internal/gc/universe.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ var builtinFuncs = [...]struct {
6565
{"recover", ORECOVER},
6666
}
6767

68+
// isBuiltinFuncName reports whether name matches a builtin function
69+
// name.
70+
func isBuiltinFuncName(name string) bool {
71+
for _, fn := range builtinFuncs {
72+
if fn.name == name {
73+
return true
74+
}
75+
}
76+
return false
77+
}
78+
6879
var unsafeFuncs = [...]struct {
6980
name string
7081
op Op

test/fixedbugs/issue22822.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// errorcheck
2+
3+
// Copyright 2018 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Check that calling a function shadowing a built-in provides a good
8+
// error message.
9+
10+
package main
11+
12+
func F() {
13+
slice := []int{1, 2, 3}
14+
len := int(2)
15+
println(len(slice)) // ERROR "cannot call non-function len .type int., declared at"
16+
}

0 commit comments

Comments
 (0)