Skip to content

Commit 8baecea

Browse files
adonovanfindleyr
authored andcommitted
gopls/internal/analysis/modernize: mapsloop: fix two bugs
As with slices.Contains, there was a bug in the maps.Copy modernizer resulting from not checking for implicit widening conversions in m[k]=v; and another, from not checking that m is a map. This CL fixes both. Modernizers are hard. :( Fixes golang/go#71313 Change-Id: Ie59aa9419868b3010435b7113bb5e67f0abbb4d3 Reviewed-on: https://go-review.googlesource.com/c/tools/+/645876 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 1320197 commit 8baecea

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

gopls/internal/analysis/modernize/maps.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,12 @@ func mapsloop(pass *analysis.Pass) {
186186
assign := rng.Body.List[0].(*ast.AssignStmt)
187187
if index, ok := assign.Lhs[0].(*ast.IndexExpr); ok &&
188188
equalSyntax(rng.Key, index.Index) &&
189-
equalSyntax(rng.Value, assign.Rhs[0]) {
189+
equalSyntax(rng.Value, assign.Rhs[0]) &&
190+
is[*types.Map](typeparams.CoreType(info.TypeOf(index.X))) &&
191+
types.Identical(info.TypeOf(index), info.TypeOf(rng.Value)) { // m[k], v
190192

191193
// Have: for k, v := range x { m[k] = v }
194+
// where there is no implicit conversion.
192195
check(file, curRange, assign, index.X, rng.X)
193196
}
194197
}

gopls/internal/analysis/modernize/testdata/src/mapsloop/mapsloop.go

+28
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ func useCopy(dst, src map[int]string) {
2020
}
2121
}
2222

23+
func useCopyGeneric[K comparable, V any, M ~map[K]V](dst, src M) {
24+
// Replace loop by maps.Copy.
25+
for key, value := range src {
26+
dst[key] = value // want "Replace m\\[k\\]=v loop with maps.Copy"
27+
}
28+
}
29+
2330
func useClone(src map[int]string) {
2431
// Replace make(...) by maps.Clone.
2532
dst := make(map[int]string, len(src))
@@ -146,3 +153,24 @@ func nopeAssignmentHasIncrementOperator(src map[int]int) {
146153
dst[k] += v
147154
}
148155
}
156+
157+
func nopeNotAMap(src map[int]string) {
158+
var dst []string
159+
for k, v := range src {
160+
dst[k] = v
161+
}
162+
}
163+
164+
func nopeNotAMapGeneric[E any, M ~map[int]E, S ~[]E](src M) {
165+
var dst S
166+
for k, v := range src {
167+
dst[k] = v
168+
}
169+
}
170+
171+
func nopeHasImplicitWidening(src map[string]int) {
172+
dst := make(map[string]any)
173+
for k, v := range src {
174+
dst[k] = v
175+
}
176+
}

gopls/internal/analysis/modernize/testdata/src/mapsloop/mapsloop.go.golden

+26
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ func useCopy(dst, src map[int]string) {
1818
maps.Copy(dst, src)
1919
}
2020

21+
func useCopyGeneric[K comparable, V any, M ~map[K]V](dst, src M) {
22+
// Replace loop by maps.Copy.
23+
maps.Copy(dst, src)
24+
}
25+
2126
func useClone(src map[int]string) {
2227
// Replace make(...) by maps.Clone.
2328
dst := maps.Clone(src)
@@ -118,3 +123,24 @@ func nopeAssignmentHasIncrementOperator(src map[int]int) {
118123
dst[k] += v
119124
}
120125
}
126+
127+
func nopeNotAMap(src map[int]string) {
128+
var dst []string
129+
for k, v := range src {
130+
dst[k] = v
131+
}
132+
}
133+
134+
func nopeNotAMapGeneric[E any, M ~map[int]E, S ~[]E](src M) {
135+
var dst S
136+
for k, v := range src {
137+
dst[k] = v
138+
}
139+
}
140+
141+
func nopeHasImplicitWidening(src map[string]int) {
142+
dst := make(map[string]any)
143+
for k, v := range src {
144+
dst[k] = v
145+
}
146+
}

0 commit comments

Comments
 (0)