diff --git a/src/cmd/vet/testdata/print.go b/src/cmd/vet/testdata/print.go index b2289bc2ac..994902d01d 100644 --- a/src/cmd/vet/testdata/print.go +++ b/src/cmd/vet/testdata/print.go @@ -234,7 +234,7 @@ func PrintfTests() { Printf("%T", someFunction) // ok: maybe someone wants to see the type // Bug: used to recur forever. Printf("%p %x", recursiveStructV, recursiveStructV.next) - Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next) + Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next) // ERROR "Printf format %x has arg recursiveStruct1V\.next of wrong type \*testdata\.RecursiveStruct2" Printf("%p %x", recursiveSliceV, recursiveSliceV) Printf("%p %x", recursiveMapV, recursiveMapV) // Special handling for Log. @@ -670,4 +670,12 @@ func PointersToCompoundTypes() { intMap := map[int]int{3: 4} fmt.Printf("%s", &intMap) // ERROR "Printf format %s has arg &intMap of wrong type \*map\[int\]int" + + type T2 struct { + X string + } + type T1 struct { + X *T2 + } + fmt.Printf("%s\n", T1{&T2{"x"}}) // ERROR "Printf format %s has arg T1{&T2{.x.}} of wrong type testdata\.T1" } diff --git a/src/cmd/vet/types.go b/src/cmd/vet/types.go index 78823aed97..8cb0e8e77d 100644 --- a/src/cmd/vet/types.go +++ b/src/cmd/vet/types.go @@ -227,9 +227,13 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp // Check whether the rest can print pointers. return t&argPointer != 0 } - // If it's a pointer to a struct, array, slice, or map, that's - // equivalent in our analysis to whether we can print the type - // being pointed to. + // If it's a top-level pointer to a struct, array, slice, or + // map, that's equivalent in our analysis to whether we can + // print the type being pointed to. Pointers in nested levels + // are not supported to minimize fmt running into loops. + if len(inProgress) > 1 { + return false + } return f.matchArgTypeInternal(t, under, arg, inProgress) case *types.Struct: