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 51550b373f88bf86b33ece5c47e305cdcdc28a86 Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Fri, 2 Oct 2026 00:01:36 +0800 Subject: [PATCH 2/3] Propagate go.mod restoration errors --- internal/xtools-internal/packagestest/expect.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/xtools-internal/packagestest/expect.go b/internal/xtools-internal/packagestest/expect.go index e55108aca..d487edb94 100644 --- a/internal/xtools-internal/packagestest/expect.go +++ b/internal/xtools-internal/packagestest/expect.go @@ -206,7 +206,7 @@ func goModMarkers(e *Exported, gomod string) ([]*expect.Note, error) { gomod = strings.TrimSuffix(gomod, ".temp") // If we are in Modules mode, copy the original contents file back into go.mod if err := os.WriteFile(gomod, content, 0644); err != nil { - return nil, nil + return nil, err } return expect.Parse(e.ExpectFileSet, gomod, content) } From 4aacb6857a07f3f867b6f02eb0768aa2c0c79688 Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Fri, 2 Oct 2026 14:20:51 +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]() -}