diff --git a/go/analysis/passes/unusedresult/testdata/src/typeparams/typeparams.go b/go/analysis/passes/unusedresult/testdata/src/typeparams/typeparams.go new file mode 100644 index 00000000000..c770ccd44e4 --- /dev/null +++ b/go/analysis/passes/unusedresult/testdata/src/typeparams/typeparams.go @@ -0,0 +1,41 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +//go:build go1.18 + +package typeparams + +import ( + "bytes" + "errors" + "fmt" + "typeparams/userdefs" +) + +func _[T any]() { + fmt.Errorf("") // want "result of fmt.Errorf call not used" + _ = fmt.Errorf("") + + errors.New("") // want "result of errors.New call not used" + + err := errors.New("") + err.Error() // want `result of \(error\).Error call not used` + + var buf bytes.Buffer + buf.String() // want `result of \(bytes.Buffer\).String call not used` + + fmt.Sprint("") // want "result of fmt.Sprint call not used" + fmt.Sprintf("") // want "result of fmt.Sprintf call not used" + + userdefs.MustUse[int](1) // want "result of typeparams/userdefs.MustUse call not used" + _ = userdefs.MustUse[int](2) + + s := userdefs.SingleTypeParam[int]{X: 1} + s.String() // want `result of \(typeparams/userdefs.SingleTypeParam\[int\]\).String call not used` + _ = s.String() + + m := userdefs.MultiTypeParam[int, string]{X: 1, Y: "one"} + m.String() // want `result of \(typeparams/userdefs.MultiTypeParam\[int, string\]\).String call not used` + _ = m.String() +} \ No newline at end of file diff --git a/go/analysis/passes/unusedresult/testdata/src/typeparams/userdefs/userdefs.go b/go/analysis/passes/unusedresult/testdata/src/typeparams/userdefs/userdefs.go new file mode 100644 index 00000000000..218cc9ac75e --- /dev/null +++ b/go/analysis/passes/unusedresult/testdata/src/typeparams/userdefs/userdefs.go @@ -0,0 +1,28 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +//go:build go1.18 + +package userdefs + +func MustUse[T interface{ ~int }](v T) T { + return v + 1 +} + +type SingleTypeParam[T any] struct { + X T +} + +func (_ *SingleTypeParam[T]) String() string { + return "SingleTypeParam" +} + +type MultiTypeParam[T any, U any] struct { + X T + Y U +} + +func (_ *MultiTypeParam[T, U]) String() string { + return "MultiTypeParam" +} \ No newline at end of file diff --git a/go/analysis/passes/unusedresult/unusedresult.go b/go/analysis/passes/unusedresult/unusedresult.go index bececee7e93..fd94508f883 100644 --- a/go/analysis/passes/unusedresult/unusedresult.go +++ b/go/analysis/passes/unusedresult/unusedresult.go @@ -17,6 +17,7 @@ import ( "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/internal/typeparams" ) // TODO(adonovan): make this analysis modular: export a mustUseResult @@ -70,6 +71,11 @@ func run(pass *analysis.Pass) (interface{}, error) { return // a conversion, not a call } + index := typeparams.GetIndexExprData(fun) + if index != nil { + fun = index.X // If this is generic function or method call, skip the instantiation arguments + } + selector, ok := fun.(*ast.SelectorExpr) if !ok { return // neither a method call nor a qualified ident diff --git a/go/analysis/passes/unusedresult/unusedresult_test.go b/go/analysis/passes/unusedresult/unusedresult_test.go index 90bf7ba4f0c..a2b079af00e 100644 --- a/go/analysis/passes/unusedresult/unusedresult_test.go +++ b/go/analysis/passes/unusedresult/unusedresult_test.go @@ -9,9 +9,16 @@ import ( "golang.org/x/tools/go/analysis/analysistest" "golang.org/x/tools/go/analysis/passes/unusedresult" + "golang.org/x/tools/internal/typeparams" ) func Test(t *testing.T) { testdata := analysistest.TestData() - analysistest.Run(t, testdata, unusedresult.Analyzer, "a") + funcs := "typeparams/userdefs.MustUse,errors.New,fmt.Errorf,fmt.Sprintf,fmt.Sprint" + unusedresult.Analyzer.Flags.Set("funcs", funcs) + tests := []string{"a"} + if typeparams.Enabled { + tests = append(tests, "typeparams") + } + analysistest.Run(t, testdata, unusedresult.Analyzer, tests...) }