Skip to content

Commit 010e045

Browse files
committed
internal/persistent: use generics
Now that we're on 1.18+, make internal/persistent.Map generic. Change-Id: I3403241fe22e28f969d7feb09a752b52f0d2ee4d Reviewed-on: https://go-review.googlesource.com/c/tools/+/524759 gopls-CI: kokoro <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Alan Donovan <[email protected]>
1 parent a1a928d commit 010e045

File tree

12 files changed

+148
-121
lines changed

12 files changed

+148
-121
lines changed

gopls/internal/lsp/cache/check.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ func (s *snapshot) getPackageHandles(ctx context.Context, ids []PackageID) (map[
849849
unfinishedSuccs: int32(len(m.DepsByPkgPath)),
850850
}
851851
if entry, hit := b.s.packages.Get(m.ID); hit {
852-
n.ph = entry.(*packageHandle)
852+
n.ph = entry
853853
}
854854
if n.unfinishedSuccs == 0 {
855855
leaves = append(leaves, n)
@@ -1118,12 +1118,11 @@ func (b *packageHandleBuilder) buildPackageHandle(ctx context.Context, n *handle
11181118
}
11191119

11201120
// Check the packages map again in case another goroutine got there first.
1121-
if alt, ok := b.s.packages.Get(n.m.ID); ok && alt.(*packageHandle).validated {
1122-
altPH := alt.(*packageHandle)
1123-
if altPH.m != n.m {
1121+
if alt, ok := b.s.packages.Get(n.m.ID); ok && alt.validated {
1122+
if alt.m != n.m {
11241123
bug.Reportf("existing package handle does not match for %s", n.m.ID)
11251124
}
1126-
n.ph = altPH
1125+
n.ph = alt
11271126
} else {
11281127
b.s.packages.Set(n.m.ID, n.ph, nil)
11291128
}

gopls/internal/lsp/cache/load.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,7 @@ func (s *snapshot) load(ctx context.Context, allowNetwork bool, scopes ...loadSc
217217
s.mu.Lock()
218218

219219
// Assert the invariant s.packages.Get(id).m == s.meta.metadata[id].
220-
s.packages.Range(func(k, v interface{}) {
221-
id, ph := k.(PackageID), v.(*packageHandle)
220+
s.packages.Range(func(id PackageID, ph *packageHandle) {
222221
if s.meta.metadata[id] != ph.m {
223222
panic("inconsistent metadata")
224223
}

gopls/internal/lsp/cache/maps.go

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,14 @@ import (
1010
"golang.org/x/tools/internal/persistent"
1111
)
1212

13-
// TODO(euroelessar): Use generics once support for go1.17 is dropped.
14-
1513
type filesMap struct {
16-
impl *persistent.Map
14+
impl *persistent.Map[span.URI, source.FileHandle]
1715
overlayMap map[span.URI]*Overlay // the subset that are overlays
1816
}
1917

20-
// uriLessInterface is the < relation for "any" values containing span.URIs.
21-
func uriLessInterface(a, b interface{}) bool {
22-
return a.(span.URI) < b.(span.URI)
23-
}
24-
2518
func newFilesMap() filesMap {
2619
return filesMap{
27-
impl: persistent.NewMap(uriLessInterface),
20+
impl: new(persistent.Map[span.URI, source.FileHandle]),
2821
overlayMap: make(map[span.URI]*Overlay),
2922
}
3023
}
@@ -53,9 +46,7 @@ func (m filesMap) Get(key span.URI) (source.FileHandle, bool) {
5346
}
5447

5548
func (m filesMap) Range(do func(key span.URI, value source.FileHandle)) {
56-
m.impl.Range(func(key, value interface{}) {
57-
do(key.(span.URI), value.(source.FileHandle))
58-
})
49+
m.impl.Range(do)
5950
}
6051

6152
func (m filesMap) Set(key span.URI, value source.FileHandle) {
@@ -86,19 +77,13 @@ func (m filesMap) overlays() []*Overlay {
8677
return overlays
8778
}
8879

89-
func packageIDLessInterface(x, y interface{}) bool {
90-
return x.(PackageID) < y.(PackageID)
91-
}
92-
9380
type knownDirsSet struct {
94-
impl *persistent.Map
81+
impl *persistent.Map[span.URI, struct{}]
9582
}
9683

9784
func newKnownDirsSet() knownDirsSet {
9885
return knownDirsSet{
99-
impl: persistent.NewMap(func(a, b interface{}) bool {
100-
return a.(span.URI) < b.(span.URI)
101-
}),
86+
impl: new(persistent.Map[span.URI, struct{}]),
10287
}
10388
}
10489

@@ -118,8 +103,8 @@ func (s knownDirsSet) Contains(key span.URI) bool {
118103
}
119104

120105
func (s knownDirsSet) Range(do func(key span.URI)) {
121-
s.impl.Range(func(key, value interface{}) {
122-
do(key.(span.URI))
106+
s.impl.Range(func(key span.URI, value struct{}) {
107+
do(key)
123108
})
124109
}
125110

@@ -128,7 +113,7 @@ func (s knownDirsSet) SetAll(other knownDirsSet) {
128113
}
129114

130115
func (s knownDirsSet) Insert(key span.URI) {
131-
s.impl.Set(key, nil, nil)
116+
s.impl.Set(key, struct{}{}, nil)
132117
}
133118

134119
func (s knownDirsSet) Remove(key span.URI) {

gopls/internal/lsp/cache/mod.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (s *snapshot) ParseMod(ctx context.Context, fh source.FileHandle) (*source.
5252
}
5353

5454
// Await result.
55-
v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
55+
v, err := s.awaitPromise(ctx, entry)
5656
if err != nil {
5757
return nil, err
5858
}
@@ -130,7 +130,7 @@ func (s *snapshot) ParseWork(ctx context.Context, fh source.FileHandle) (*source
130130
}
131131

132132
// Await result.
133-
v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
133+
v, err := s.awaitPromise(ctx, entry)
134134
if err != nil {
135135
return nil, err
136136
}
@@ -240,7 +240,7 @@ func (s *snapshot) ModWhy(ctx context.Context, fh source.FileHandle) (map[string
240240
}
241241

242242
// Await result.
243-
v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
243+
v, err := s.awaitPromise(ctx, entry)
244244
if err != nil {
245245
return nil, err
246246
}

gopls/internal/lsp/cache/mod_tidy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (s *snapshot) ModTidy(ctx context.Context, pm *source.ParsedModule) (*sourc
8585
}
8686

8787
// Await result.
88-
v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
88+
v, err := s.awaitPromise(ctx, entry)
8989
if err != nil {
9090
return nil, err
9191
}

gopls/internal/lsp/cache/mod_vuln.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func (s *snapshot) ModVuln(ctx context.Context, modURI span.URI) (*govulncheck.R
5555
}
5656

5757
// Await result.
58-
v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
58+
v, err := s.awaitPromise(ctx, entry)
5959
if err != nil {
6060
return nil, err
6161
}

gopls/internal/lsp/cache/session.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"golang.org/x/tools/internal/event"
2121
"golang.org/x/tools/internal/gocommand"
2222
"golang.org/x/tools/internal/imports"
23+
"golang.org/x/tools/internal/memoize"
2324
"golang.org/x/tools/internal/persistent"
2425
"golang.org/x/tools/internal/xcontext"
2526
)
@@ -169,18 +170,18 @@ func (s *Session) createView(ctx context.Context, name string, folder span.URI,
169170
backgroundCtx: backgroundCtx,
170171
cancel: cancel,
171172
store: s.cache.store,
172-
packages: persistent.NewMap(packageIDLessInterface),
173+
packages: new(persistent.Map[PackageID, *packageHandle]),
173174
meta: new(metadataGraph),
174175
files: newFilesMap(),
175-
activePackages: persistent.NewMap(packageIDLessInterface),
176-
symbolizeHandles: persistent.NewMap(uriLessInterface),
176+
activePackages: new(persistent.Map[PackageID, *Package]),
177+
symbolizeHandles: new(persistent.Map[span.URI, *memoize.Promise]),
177178
workspacePackages: make(map[PackageID]PackagePath),
178179
unloadableFiles: make(map[span.URI]struct{}),
179-
parseModHandles: persistent.NewMap(uriLessInterface),
180-
parseWorkHandles: persistent.NewMap(uriLessInterface),
181-
modTidyHandles: persistent.NewMap(uriLessInterface),
182-
modVulnHandles: persistent.NewMap(uriLessInterface),
183-
modWhyHandles: persistent.NewMap(uriLessInterface),
180+
parseModHandles: new(persistent.Map[span.URI, *memoize.Promise]),
181+
parseWorkHandles: new(persistent.Map[span.URI, *memoize.Promise]),
182+
modTidyHandles: new(persistent.Map[span.URI, *memoize.Promise]),
183+
modVulnHandles: new(persistent.Map[span.URI, *memoize.Promise]),
184+
modWhyHandles: new(persistent.Map[span.URI, *memoize.Promise]),
184185
knownSubdirs: newKnownDirsSet(),
185186
workspaceModFiles: wsModFiles,
186187
workspaceModFilesErr: wsModFilesErr,

gopls/internal/lsp/cache/snapshot.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ type snapshot struct {
101101

102102
// symbolizeHandles maps each file URI to a handle for the future
103103
// result of computing the symbols declared in that file.
104-
symbolizeHandles *persistent.Map // from span.URI to *memoize.Promise[symbolizeResult]
104+
symbolizeHandles *persistent.Map[span.URI, *memoize.Promise] // *memoize.Promise[symbolizeResult]
105105

106106
// packages maps a packageKey to a *packageHandle.
107107
// It may be invalidated when a file's content changes.
@@ -110,13 +110,13 @@ type snapshot struct {
110110
// - packages.Get(id).meta == meta.metadata[id] for all ids
111111
// - if a package is in packages, then all of its dependencies should also
112112
// be in packages, unless there is a missing import
113-
packages *persistent.Map // from packageID to *packageHandle
113+
packages *persistent.Map[PackageID, *packageHandle]
114114

115115
// activePackages maps a package ID to a memoized active package, or nil if
116116
// the package is known not to be open.
117117
//
118118
// IDs not contained in the map are not known to be open or not open.
119-
activePackages *persistent.Map // from packageID to *Package
119+
activePackages *persistent.Map[PackageID, *Package]
120120

121121
// workspacePackages contains the workspace's packages, which are loaded
122122
// when the view is created. It contains no intermediate test variants.
@@ -137,18 +137,18 @@ type snapshot struct {
137137

138138
// parseModHandles keeps track of any parseModHandles for the snapshot.
139139
// The handles need not refer to only the view's go.mod file.
140-
parseModHandles *persistent.Map // from span.URI to *memoize.Promise[parseModResult]
140+
parseModHandles *persistent.Map[span.URI, *memoize.Promise] // *memoize.Promise[parseModResult]
141141

142142
// parseWorkHandles keeps track of any parseWorkHandles for the snapshot.
143143
// The handles need not refer to only the view's go.work file.
144-
parseWorkHandles *persistent.Map // from span.URI to *memoize.Promise[parseWorkResult]
144+
parseWorkHandles *persistent.Map[span.URI, *memoize.Promise] // *memoize.Promise[parseWorkResult]
145145

146146
// Preserve go.mod-related handles to avoid garbage-collecting the results
147147
// of various calls to the go command. The handles need not refer to only
148148
// the view's go.mod file.
149-
modTidyHandles *persistent.Map // from span.URI to *memoize.Promise[modTidyResult]
150-
modWhyHandles *persistent.Map // from span.URI to *memoize.Promise[modWhyResult]
151-
modVulnHandles *persistent.Map // from span.URI to *memoize.Promise[modVulnResult]
149+
modTidyHandles *persistent.Map[span.URI, *memoize.Promise] // *memoize.Promise[modTidyResult]
150+
modWhyHandles *persistent.Map[span.URI, *memoize.Promise] // *memoize.Promise[modWhyResult]
151+
modVulnHandles *persistent.Map[span.URI, *memoize.Promise] // *memoize.Promise[modVulnResult]
152152

153153
// knownSubdirs is the set of subdirectory URIs in the workspace,
154154
// used to create glob patterns for file watching.
@@ -871,7 +871,7 @@ func (s *snapshot) getActivePackage(id PackageID) *Package {
871871
defer s.mu.Unlock()
872872

873873
if value, ok := s.activePackages.Get(id); ok {
874-
return value.(*Package) // possibly nil, if we have already checked this id.
874+
return value
875875
}
876876
return nil
877877
}
@@ -895,7 +895,7 @@ func (s *snapshot) setActivePackage(id PackageID, pkg *Package) {
895895

896896
func (s *snapshot) resetActivePackagesLocked() {
897897
s.activePackages.Destroy()
898-
s.activePackages = persistent.NewMap(packageIDLessInterface)
898+
s.activePackages = new(persistent.Map[PackageID, *Package])
899899
}
900900

901901
const fileExtensions = "go,mod,sum,work"
@@ -2189,7 +2189,7 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
21892189
result.packages.Delete(id)
21902190
} else {
21912191
if entry, hit := result.packages.Get(id); hit {
2192-
ph := entry.(*packageHandle).clone(false)
2192+
ph := entry.clone(false)
21932193
result.packages.Set(id, ph, nil)
21942194
}
21952195
}
@@ -2291,12 +2291,11 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
22912291
// changed that happens not to be present in the map, but that's OK: the goal
22922292
// of this function is to guarantee that IF the nearest mod file is present in
22932293
// the map, it is invalidated.
2294-
func deleteMostRelevantModFile(m *persistent.Map, changed span.URI) {
2294+
func deleteMostRelevantModFile(m *persistent.Map[span.URI, *memoize.Promise], changed span.URI) {
22952295
var mostRelevant span.URI
22962296
changedFile := changed.Filename()
22972297

2298-
m.Range(func(key, value interface{}) {
2299-
modURI := key.(span.URI)
2298+
m.Range(func(modURI span.URI, _ *memoize.Promise) {
23002299
if len(modURI) > len(mostRelevant) {
23012300
if source.InDir(filepath.Dir(modURI.Filename()), changedFile) {
23022301
mostRelevant = modURI

gopls/internal/lsp/cache/symbols.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"golang.org/x/tools/gopls/internal/lsp/protocol"
1616
"golang.org/x/tools/gopls/internal/lsp/source"
1717
"golang.org/x/tools/gopls/internal/span"
18-
"golang.org/x/tools/internal/memoize"
1918
)
2019

2120
// symbolize returns the result of symbolizing the file identified by uri, using a cache.
@@ -51,7 +50,7 @@ func (s *snapshot) symbolize(ctx context.Context, uri span.URI) ([]source.Symbol
5150
}
5251

5352
// Await result.
54-
v, err := s.awaitPromise(ctx, entry.(*memoize.Promise))
53+
v, err := s.awaitPromise(ctx, entry)
5554
if err != nil {
5655
return nil, err
5756
}

internal/constraints/constraint.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package constraints defines a set of useful constraints to be used
6+
// with type parameters.
7+
package constraints
8+
9+
// Copied from x/exp/constraints.
10+
11+
// Signed is a constraint that permits any signed integer type.
12+
// If future releases of Go add new predeclared signed integer types,
13+
// this constraint will be modified to include them.
14+
type Signed interface {
15+
~int | ~int8 | ~int16 | ~int32 | ~int64
16+
}
17+
18+
// Unsigned is a constraint that permits any unsigned integer type.
19+
// If future releases of Go add new predeclared unsigned integer types,
20+
// this constraint will be modified to include them.
21+
type Unsigned interface {
22+
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
23+
}
24+
25+
// Integer is a constraint that permits any integer type.
26+
// If future releases of Go add new predeclared integer types,
27+
// this constraint will be modified to include them.
28+
type Integer interface {
29+
Signed | Unsigned
30+
}
31+
32+
// Float is a constraint that permits any floating-point type.
33+
// If future releases of Go add new predeclared floating-point types,
34+
// this constraint will be modified to include them.
35+
type Float interface {
36+
~float32 | ~float64
37+
}
38+
39+
// Complex is a constraint that permits any complex numeric type.
40+
// If future releases of Go add new predeclared complex numeric types,
41+
// this constraint will be modified to include them.
42+
type Complex interface {
43+
~complex64 | ~complex128
44+
}
45+
46+
// Ordered is a constraint that permits any ordered type: any type
47+
// that supports the operators < <= >= >.
48+
// If future releases of Go add new ordered types,
49+
// this constraint will be modified to include them.
50+
type Ordered interface {
51+
Integer | Float | ~string
52+
}

0 commit comments

Comments
 (0)