go/analysis/passes/unmarshal: allow unmarshalling to a type parameter
We can also unmarshal data to a type parameter, in addition to a pointer
and an interface.
This analyzer probably requires more discussion, but this solution
should be sufficient for now.
Updates golang/go#48704
Change-Id: I333f919109295e80a04e59df131713553cdbe612
Reviewed-on: https://go-review.googlesource.com/c/tools/+/353210
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Trust: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
diff --git a/go/analysis/passes/unmarshal/testdata/src/typeparams/typeparams.go b/go/analysis/passes/unmarshal/testdata/src/typeparams/typeparams.go
new file mode 100644
index 0000000..cbf7deb
--- /dev/null
+++ b/go/analysis/passes/unmarshal/testdata/src/typeparams/typeparams.go
@@ -0,0 +1,22 @@
+package typeparams
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+func unmarshalT[T any](data []byte) T {
+ var x T
+ json.Unmarshal(data, x)
+ return x
+}
+
+func unmarshalT2[T any](data []byte, t T) {
+ json.Unmarshal(data, t)
+}
+
+func main() {
+ x := make(map[string]interface{})
+ unmarshalT2([]byte(`{"a":1}`), &x)
+ fmt.Println(x)
+}
\ No newline at end of file
diff --git a/go/analysis/passes/unmarshal/unmarshal.go b/go/analysis/passes/unmarshal/unmarshal.go
index 92b37ca..5129048 100644
--- a/go/analysis/passes/unmarshal/unmarshal.go
+++ b/go/analysis/passes/unmarshal/unmarshal.go
@@ -14,6 +14,7 @@
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/go/types/typeutil"
+ "golang.org/x/tools/internal/typeparams"
)
const Doc = `report passing non-pointer or non-interface values to unmarshal
@@ -85,7 +86,7 @@
t := pass.TypesInfo.Types[call.Args[argidx]].Type
switch t.Underlying().(type) {
- case *types.Pointer, *types.Interface:
+ case *types.Pointer, *types.Interface, *typeparams.TypeParam:
return
}
diff --git a/go/analysis/passes/unmarshal/unmarshal_test.go b/go/analysis/passes/unmarshal/unmarshal_test.go
index ae19e5d..e6171f2 100644
--- a/go/analysis/passes/unmarshal/unmarshal_test.go
+++ b/go/analysis/passes/unmarshal/unmarshal_test.go
@@ -9,9 +9,14 @@
"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/go/analysis/passes/unmarshal"
+ "golang.org/x/tools/internal/typeparams"
)
func Test(t *testing.T) {
testdata := analysistest.TestData()
- analysistest.Run(t, testdata, unmarshal.Analyzer, "a")
+ tests := []string{"a"}
+ if typeparams.Enabled {
+ tests = append(tests, "typeparams")
+ }
+ analysistest.Run(t, testdata, unmarshal.Analyzer, tests...)
}