From fc2e860eda39f6bcbe1fecac7b92a50598d1fab9 Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Thu, 1 Oct 2026 22:18:19 +0800 Subject: [PATCH 1/3] go/ir: avoid canonicalizing function signatures --- go/ir/instantiate.go | 5 ++++- internal/passes/buildir/buildir_test.go | 6 ++++++ .../testdata/src/issue1749/issue1749.go | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 internal/passes/buildir/testdata/src/issue1749/issue1749.go diff --git a/go/ir/instantiate.go b/go/ir/instantiate.go index bcb6d9a89..cfdf16e01 100644 --- a/go/ir/instantiate.go +++ b/go/ir/instantiate.go @@ -97,7 +97,10 @@ func createInstance(fn *Function, rtargs, targs []types.Type) *Function { panic("Instantiate of a Signature returned a non-signature") } obj = fn.object // instantiation does not exist yet - sig = prog.canon.Type(instance).(*types.Signature) + // Do not canonicalize signatures here. Receiver types are not part of + // signature identity, so a function signature may otherwise reuse a + // previously canonicalized method signature with a receiver. + sig = instance } // Choose strategy (instance or wrapper). diff --git a/internal/passes/buildir/buildir_test.go b/internal/passes/buildir/buildir_test.go index fe78b3af3..358104ff7 100644 --- a/internal/passes/buildir/buildir_test.go +++ b/internal/passes/buildir/buildir_test.go @@ -11,6 +11,7 @@ import ( "golang.org/x/tools/go/analysis/analysistest" "honnef.co/go/tools/internal/passes/buildir" + "honnef.co/go/tools/internal/xtools-internal/testenv" ) func Test(t *testing.T) { @@ -26,3 +27,8 @@ func Test(t *testing.T) { } } } + +func TestGenericMethodValueWithGenericFunction(t *testing.T) { + testenv.NeedsGoCommand1Point(t, 27) + analysistest.Run(t, analysistest.TestData(), buildir.Analyzer, "issue1749") +} diff --git a/internal/passes/buildir/testdata/src/issue1749/issue1749.go b/internal/passes/buildir/testdata/src/issue1749/issue1749.go new file mode 100644 index 000000000..03f424749 --- /dev/null +++ b/internal/passes/buildir/testdata/src/issue1749/issue1749.go @@ -0,0 +1,18 @@ +package issue1749 + +type T struct{} + +func (T) M[P any]() P { + var zero P + return zero +} + +func G[P any]() P { + var zero P + return zero +} + +func F(t T) string { + f := t.M[string] + return f() + G[string]() +} From 40d246740e9e68c0c0eeafaff979e70cfcc1f81b Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Fri, 2 Oct 2026 00:52:30 +0800 Subject: [PATCH 2/3] Reject unsupported XML basic types --- staticcheck/fakexml/marshal.go | 14 +++++++++++++- .../CheckUnsupportedMarshal.go | 8 ++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/staticcheck/fakexml/marshal.go b/staticcheck/fakexml/marshal.go index 9c71e8632..97077c596 100644 --- a/staticcheck/fakexml/marshal.go +++ b/staticcheck/fakexml/marshal.go @@ -289,7 +289,19 @@ func (e *Encoder) marshalAttr(start *StartElement, name Name, val fakereflect.Ty func (e *Encoder) marshalSimple(val fakereflect.TypeAndCanAddr, stack string) error { switch val.Type.Underlying().(type) { - case *types.Basic, *types.Interface: + case *types.Basic: + basic := val.Type.Underlying().(*types.Basic) + switch basic.Kind() { + case types.Bool, + types.Int, types.Int8, types.Int16, types.Int32, types.Int64, + types.Uint, types.Uint8, types.Uint16, types.Uint32, types.Uint64, types.Uintptr, + types.Float32, types.Float64, types.String, + types.UntypedBool, types.UntypedInt, types.UntypedRune, types.UntypedFloat, types.UntypedString, types.UntypedNil: + return nil + default: + return &UnsupportedTypeError{val.Type, stack} + } + case *types.Interface: return nil case *types.Slice, *types.Array: basic, ok := val.Elem().Type.Underlying().(*types.Basic) diff --git a/staticcheck/sa1026/testdata/go1.0/CheckUnsupportedMarshal/CheckUnsupportedMarshal.go b/staticcheck/sa1026/testdata/go1.0/CheckUnsupportedMarshal/CheckUnsupportedMarshal.go index 2ae94692c..40fb0b808 100644 --- a/staticcheck/sa1026/testdata/go1.0/CheckUnsupportedMarshal/CheckUnsupportedMarshal.go +++ b/staticcheck/sa1026/testdata/go1.0/CheckUnsupportedMarshal/CheckUnsupportedMarshal.go @@ -4,6 +4,7 @@ import ( "encoding/json" "encoding/xml" "time" + "unsafe" ) type T1 struct { @@ -281,6 +282,13 @@ func otherPackageXML() { xml.Marshal(x) //@ diag(`unsupported type <-chan time.Time, via x.C`) } +func unsupportedXMLBasicTypes() { + var c complex128 + var p unsafe.Pointer + xml.Marshal(c) //@ diag(`unsupported type complex128`) + xml.Marshal(p) //@ diag(`unsupported type unsafe.Pointer`) +} + type ToplevelPointerMarshalerXML struct { Field map[string]string } From 2a4347a23d5b14a240f21dc21b1451aad4e8f592 Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Fri, 2 Oct 2026 14:15:15 +0800 Subject: [PATCH 3/3] Keep fix independent of generic IR change --- go/ir/instantiate.go | 5 +---- internal/passes/buildir/buildir_test.go | 6 ------ .../testdata/src/issue1749/issue1749.go | 18 ------------------ 3 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 internal/passes/buildir/testdata/src/issue1749/issue1749.go diff --git a/go/ir/instantiate.go b/go/ir/instantiate.go index cfdf16e01..bcb6d9a89 100644 --- a/go/ir/instantiate.go +++ b/go/ir/instantiate.go @@ -97,10 +97,7 @@ func createInstance(fn *Function, rtargs, targs []types.Type) *Function { panic("Instantiate of a Signature returned a non-signature") } obj = fn.object // instantiation does not exist yet - // Do not canonicalize signatures here. Receiver types are not part of - // signature identity, so a function signature may otherwise reuse a - // previously canonicalized method signature with a receiver. - sig = instance + sig = prog.canon.Type(instance).(*types.Signature) } // Choose strategy (instance or wrapper). diff --git a/internal/passes/buildir/buildir_test.go b/internal/passes/buildir/buildir_test.go index 358104ff7..fe78b3af3 100644 --- a/internal/passes/buildir/buildir_test.go +++ b/internal/passes/buildir/buildir_test.go @@ -11,7 +11,6 @@ import ( "golang.org/x/tools/go/analysis/analysistest" "honnef.co/go/tools/internal/passes/buildir" - "honnef.co/go/tools/internal/xtools-internal/testenv" ) func Test(t *testing.T) { @@ -27,8 +26,3 @@ func Test(t *testing.T) { } } } - -func TestGenericMethodValueWithGenericFunction(t *testing.T) { - testenv.NeedsGoCommand1Point(t, 27) - analysistest.Run(t, analysistest.TestData(), buildir.Analyzer, "issue1749") -} diff --git a/internal/passes/buildir/testdata/src/issue1749/issue1749.go b/internal/passes/buildir/testdata/src/issue1749/issue1749.go deleted file mode 100644 index 03f424749..000000000 --- a/internal/passes/buildir/testdata/src/issue1749/issue1749.go +++ /dev/null @@ -1,18 +0,0 @@ -package issue1749 - -type T struct{} - -func (T) M[P any]() P { - var zero P - return zero -} - -func G[P any]() P { - var zero P - return zero -} - -func F(t T) string { - f := t.M[string] - return f() + G[string]() -}