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.
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"
}
// 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: