Commit 11e93aa2 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/vet: allow any printf verb with any interface

fmt treats interfaces as being transparent.
As a result, we cannot say with confidence
that any particular verb is wrong.

This fixes the following vet false positives
in the standard library:

database/sql/sql_test.go:210: arg dep for printf verb %p of wrong type: sql.finalCloser
fmt/fmt_test.go:1663: arg nil for printf verb %s of wrong type: untyped nil
go/ast/commentmap.go:328: arg node for printf verb %p of wrong type: ast.Node
net/http/transport_test.go:120: arg c for printf verb %p of wrong type: net.Conn
net/http/httptest/server.go:198: arg c for printf verb %p of wrong type: net.Conn
net/http/httputil/dump_test.go:258: arg body for printf verb %p of wrong type: io.Reader
reflect/set_test.go:81: arg x for printf verb %p of wrong type: io.Writer
reflect/set_test.go:141: arg bb for printf verb %p of wrong type: io.Reader

Updates #11041
Updates #16314

Change-Id: I76df01abb3c34a97b6960f551bed9c1c91377cfc
Reviewed-on: https://go-review.googlesource.com/27127
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRob Pike <r@golang.org>
parent 0ece9c4b
...@@ -199,6 +199,11 @@ func PrintfTests() { ...@@ -199,6 +199,11 @@ func PrintfTests() {
et4.Error() // ok, not an error method. et4.Error() // ok, not an error method.
var et5 errorTest5 var et5 errorTest5
et5.error() // ok, not an error method. et5.error() // ok, not an error method.
// Interfaces can be used with any verb.
var iface interface {
ToTheMadness() bool // Method ToTheMadness usually returns false
}
fmt.Printf("%f", iface) // ok: fmt treats interfaces as transparent and iface may well have a float concrete type
// Can't print a function. // Can't print a function.
Printf("%d", someFunction) // ERROR "arg someFunction in printf call is a function value, not a function call" Printf("%d", someFunction) // ERROR "arg someFunction in printf call is a function value, not a function call"
Printf("%v", someFunction) // ERROR "arg someFunction in printf call is a function value, not a function call" Printf("%v", someFunction) // ERROR "arg someFunction in printf call is a function value, not a function call"
......
...@@ -185,13 +185,10 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp ...@@ -185,13 +185,10 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp
return f.matchStructArgType(t, typ, arg, inProgress) return f.matchStructArgType(t, typ, arg, inProgress)
case *types.Interface: case *types.Interface:
// If the static type of the argument is empty interface, there's little we can do. // There's little we can do.
// Example: // Whether any particular verb is valid depends on the argument.
// func f(x interface{}) { fmt.Printf("%s", x) } // The user may have reasonable prior knowledge of the contents of the interface.
// Whether x is valid for %s depends on the type of the argument to f. One day return true
// we will be able to do better. For now, we assume that empty interface is OK
// but non-empty interfaces, with Stringer and Error handled above, are errors.
return typ.NumMethods() == 0
case *types.Basic: case *types.Basic:
switch typ.Kind() { switch typ.Kind() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment