Skip to content

Commit

Permalink
gopls/internal/cache/methodsets: support generics
Browse files Browse the repository at this point in the history
This CL adds support to gopls' index of methodsets to enable
matching of generic types and their methods. Previously, the
index was based on the notion of "fingerprints", strings that
encode the type of a method such that fingerprints are equal
if and only if types are equal. Of course this does not work
for generic types, which can match multiple distinct types.

This change redesigns the fingerprint encoding so that it
preserves the tree structure of the type, allowing it to be
parsed again later, supporting tree-based matching such
as unification. (The encoding is about 30% bigger.)

The actual tree matching in this CL is
very simple: each type parameter is treated as a wildcard
that can match any subtree at all, without regard to
consistency of substitution (as in true unification),
nor to type parameter constraint satisfaction.
Full unification would reduce false positives, but is
not urgently needed.

This CL addresses only the global algorithm using the
methodsets index. See CL 634596 for the local (type-based)
algorithm.

+ Test, relnote, doc

Updates golang/go#59224

Change-Id: I670511a8e5ce02ab23ff7b7bd60e7bd7b43c1cca
Reviewed-on: https://go-review.googlesource.com/c/tools/+/634197
Auto-Submit: Alan Donovan <adonovan@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
adonovan authored and gopherbot committed Dec 9, 2024
1 parent c2df0ef commit 7790f2e
Show file tree
Hide file tree
Showing 9 changed files with 684 additions and 212 deletions.
9 changes: 8 additions & 1 deletion gopls/doc/features/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,14 @@ types with methods due to embedding) may be missing from the results.
but that is not consistent with the "scalable" gopls design.
-->

Generic types are currently not fully supported; see golang/go#59224.
If either the target type or the candidate type are generic, the
results will include the candidate type if there is any instantiation
of the two types that would allow one to implement the other.
(Note: the matcher doesn't current implement full unification, so type
parameters are treated like wildcards that may match arbitrary
types, without regard to consistency of substitutions across the
method set or even within a single method.
This may lead to occasional spurious matches.)

Client support:
- **VS Code**: Use [Go to Implementations](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-implementation) (`⌘F12`).
Expand Down
28 changes: 28 additions & 0 deletions gopls/doc/release/v0.18.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Configuration Changes

# New features

## "Implementations" supports generics

At long last, the "Go to Implementations" feature now fully supports
generic types and functions (#59224).

For example, invoking the feature on the interface method `Stack.Push`
below will report the concrete method `C[T].Push`, and vice versa.

```go
package p

type Stack[T any] interface {
Push(T) error
Pop() (T, bool)
}

type C[T any] struct{}

func (C[T]) Push(t T) error { ... }
func (C[T]) Pop() (T, bool) { ... }

var _ Stack[int] = C[int]{}
```

Loading

0 comments on commit 7790f2e

Please sign in to comment.