From 03562de2546b298a797f4c85f240145e229b63e5 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 27 Jul 2023 13:08:51 -0400 Subject: [PATCH] refactor/satisfy/find: composite lits may have type parameter type Fix an oversight in the satisfaction check: composite lits may indeed have type parameter type, and therefore we must consider their core type. Fixes golang/go#61614 Change-Id: I2119ba308816d02742d8e790f8cd00c4d862e789 Reviewed-on: https://go-review.googlesource.com/c/tools/+/513775 Reviewed-by: Hyang-Ah Hana Kim gopls-CI: kokoro TryBot-Result: Gopher Robot Run-TryBot: Robert Findley --- .../marker/testdata/rename/issue61614.txt | 35 +++++++++++++++++++ refactor/satisfy/find.go | 3 +- refactor/satisfy/find_test.go | 9 +++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 gopls/internal/regtest/marker/testdata/rename/issue61614.txt diff --git a/gopls/internal/regtest/marker/testdata/rename/issue61614.txt b/gopls/internal/regtest/marker/testdata/rename/issue61614.txt new file mode 100644 index 00000000000..cfb37b19ac5 --- /dev/null +++ b/gopls/internal/regtest/marker/testdata/rename/issue61614.txt @@ -0,0 +1,35 @@ +This test renames a method of a type in a package that uses type parameter +composite lits. Previous iterations of the satisfy analysis did not account for +this language feature. + +See issue #60789. + +-- flags -- +-min_go=go1.18 + +-- go.mod -- +module example.com +go 1.20 + +-- a.go -- +package a + +type I int + +func (I) m() {} //@rename("m", M, mToM) + +func _[P ~[]int]() { + _ = P{} +} + +-- @mToM/a.go -- +package a + +type I int + +func (I) M() {} //@rename("m", M, mToM) + +func _[P ~[]int]() { + _ = P{} +} + diff --git a/refactor/satisfy/find.go b/refactor/satisfy/find.go index 6b4d5284aec..47dc97e471c 100644 --- a/refactor/satisfy/find.go +++ b/refactor/satisfy/find.go @@ -355,8 +355,7 @@ func (f *Finder) expr(e ast.Expr) types.Type { f.sig = saved case *ast.CompositeLit: - // No need for coreType here: go1.18 disallows P{...} for type param P. - switch T := deref(tv.Type).Underlying().(type) { + switch T := coreType(tv.Type).(type) { case *types.Struct: for i, elem := range e.Elts { if kv, ok := elem.(*ast.KeyValueExpr); ok { diff --git a/refactor/satisfy/find_test.go b/refactor/satisfy/find_test.go index 35a1e87caf4..2cbd8c15ca3 100644 --- a/refactor/satisfy/find_test.go +++ b/refactor/satisfy/find_test.go @@ -57,6 +57,8 @@ type S struct{impl} type T struct{impl} type U struct{impl} type V struct{impl} +type W struct{impl} +type X struct{impl} type Generic[T any] struct{impl} func (Generic[T]) g(T) {} @@ -164,6 +166,11 @@ func _() { // golang/go#56227: the finder should visit calls in the unsafe package. _ = unsafe.Slice(&x[0], func() int { var _ I = x[0]; return 3 }()) // I <- V } + +func _[P ~struct{F I}]() { + _ = P{W{}} + _ = P{F: X{}} +} ` got := constraints(t, src) want := []string{ @@ -194,6 +201,8 @@ func _() { "p.I <- p.T", "p.I <- p.U", "p.I <- p.V", + "p.I <- p.W", + "p.I <- p.X", } if !reflect.DeepEqual(got, want) { t.Fatalf("found unexpected constraints: got %s, want %s", got, want)