Skip to content

Commit 199742a

Browse files
committed
go/analysis/passes/printf: check for nil scope of instance methods
Fixes golang/go#55350 Change-Id: I28784b42de72e9d489e40d546e171af23b9e5c13 Reviewed-on: https://go-review.googlesource.com/c/tools/+/433755 gopls-CI: kokoro <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Tim King <[email protected]> Run-TryBot: Zvonimir Pavlinovic <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 3db607b commit 199742a

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

go/analysis/passes/printf/printf.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -945,11 +945,16 @@ func recursiveStringer(pass *analysis.Pass, e ast.Expr) (string, bool) {
945945
return "", false
946946
}
947947

948+
// inScope returns true if e is in the scope of f.
949+
inScope := func(e ast.Expr, f *types.Func) bool {
950+
return f.Scope() != nil && f.Scope().Contains(e.Pos())
951+
}
952+
948953
// Is the expression e within the body of that String or Error method?
949954
var method *types.Func
950-
if strOk && strMethod.Pkg() == pass.Pkg && strMethod.Scope().Contains(e.Pos()) {
955+
if strOk && strMethod.Pkg() == pass.Pkg && inScope(e, strMethod) {
951956
method = strMethod
952-
} else if errOk && errMethod.Pkg() == pass.Pkg && errMethod.Scope().Contains(e.Pos()) {
957+
} else if errOk && errMethod.Pkg() == pass.Pkg && inScope(e, errMethod) {
953958
method = errMethod
954959
} else {
955960
return "", false

go/analysis/passes/printf/testdata/src/typeparams/diagnostics.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,25 @@ func TestTermReduction[T1 interface{ ~int | string }, T2 interface {
121121
fmt.Printf("%d", t2)
122122
fmt.Printf("%s", t2) // want "wrong type.*contains typeparams.myInt"
123123
}
124+
125+
type U[T any] struct{}
126+
127+
func (u U[T]) String() string {
128+
fmt.Println(u) // want `fmt.Println arg u causes recursive call to \(typeparams.U\[T\]\).String method`
129+
return ""
130+
}
131+
132+
type S[T comparable] struct {
133+
t T
134+
}
135+
136+
func (s S[T]) String() T {
137+
fmt.Println(s) // Not flagged. We currently do not consider String() T to implement fmt.Stringer (see #55928).
138+
return s.t
139+
}
140+
141+
func TestInstanceStringer() {
142+
// Tests String method with nil Scope (#55350)
143+
fmt.Println(&S[string]{})
144+
fmt.Println(&U[string]{})
145+
}

0 commit comments

Comments
 (0)