From 2a8b9debdde0307f91248528a6fd60ad14a810da Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 30 Jul 2013 15:51:35 +1000 Subject: [PATCH] go.tools/cmd/vet: don't complain about empty interface values in printf R=dsymonds CC=golang-dev https://golang.org/cl/12005047 --- cmd/vet/testdata/print.go | 8 +++++++- cmd/vet/types.go | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/cmd/vet/testdata/print.go b/cmd/vet/testdata/print.go index 0440e3484a..a703825de8 100644 --- a/cmd/vet/testdata/print.go +++ b/cmd/vet/testdata/print.go @@ -88,7 +88,8 @@ func PrintfTests() { fmt.Printf("%s", stringerarrayv) fmt.Printf("%v", notstringerarrayv) fmt.Printf("%T", notstringerarrayv) - fmt.Printf("%*%", 2) // Ridiculous but allowed. + fmt.Printf("%*%", 2) // Ridiculous but allowed. + fmt.Printf("%s", interface{}(nil)) // Nothing useful we can say. fmt.Printf("%g", 1+2i) // Some bad format/argTypes @@ -120,6 +121,7 @@ func PrintfTests() { fmt.Printf("%t", stringerarrayv) // ERROR "arg stringerarrayv for printf verb %t of wrong type" fmt.Printf("%t", notstringerarrayv) // ERROR "arg notstringerarrayv for printf verb %t of wrong type" fmt.Printf("%q", notstringerarrayv) // ERROR "arg notstringerarrayv for printf verb %q of wrong type" + fmt.Printf("%s", nonemptyinterface) // ERROR "for printf verb %s of wrong type" fmt.Printf("%.*s %d %g", 3, "hi", 23, 'x') // ERROR "arg 'x' for printf verb %g of wrong type" fmt.Println() // not an error fmt.Println("%s", "hi") // ERROR "possible formatting directive in Println call" @@ -227,3 +229,7 @@ var stringerarrayv stringerarray type notstringerarray [4]float64 var notstringerarrayv notstringerarray + +var nonemptyinterface = interface { + f() +}(nil) diff --git a/cmd/vet/types.go b/cmd/vet/types.go index 9fd00ee737..624f71afc8 100644 --- a/cmd/vet/types.go +++ b/cmd/vet/types.go @@ -132,6 +132,15 @@ func (f *File) matchArgType(t printfArgType, typ types.Type, arg ast.Expr) bool } return t&argPointer != 0 + case *types.Interface: + // If the static type of the argument is empty interface, there's little we can do. + // Example: + // func f(x interface{}) { fmt.Printf("%s", x) } + // Whether x is valid for %s depends on the type of the argument to f. One day + // 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: switch typ.Kind() { case types.UntypedBool,