blob: 9136105b90858565b9901629022d6febfe78db7d [file] [log] [blame]
//go:build go1.23
package mapsloop
import (
"iter"
"maps"
)
var _ = maps.Clone[M] // force "maps" import so that each diagnostic doesn't add one
type M map[int]string
// -- src is map --
func useCopy(dst, src map[int]string) {
// Replace loop by maps.Copy.
// A
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
}
func useCopyGeneric[K comparable, V any, M ~map[K]V](dst, src M) {
// Replace loop by maps.Copy.
// A
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
}
func useCopyNotClone(src map[int]string) {
// Clone is tempting but wrong when src may be nil; see #71844.
// Replace make(...) by maps.Copy.
dst := make(map[int]string, len(src))
// A
// B
// want "Replace m\\[k\\]=v loop with maps.Copy"
// C
maps.Copy(dst, src)
// A
dst = map[int]string{}
// B
// C
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
println(dst)
}
func useCopyParen(src map[int]string) {
// Clone is tempting but wrong when src may be nil; see #71844.
// Replace (make)(...) by maps.Clone.
dst := (make)(map[int]string, len(src))
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
dst = (map[int]string{})
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
println(dst)
}
func useCopy_typesDiffer(src M) {
// Replace loop but not make(...) as maps.Copy(src) would return wrong type M.
dst := make(map[int]string, len(src))
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
println(dst)
}
func useCopy_typesDiffer2(src map[int]string) {
// Replace loop but not make(...) as maps.Copy(src) would return wrong type map[int]string.
dst := make(M, len(src))
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
println(dst)
}
func useClone_typesDiffer3(src map[int]string) {
// Clone is tempting but wrong when src may be nil; see #71844.
// Replace loop and make(...) as maps.Clone(src) returns map[int]string
// which is assignable to M.
var dst M
dst = make(M, len(src))
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
println(dst)
}
func useClone_typesDiffer4(src map[int]string) {
// Clone is tempting but wrong when src may be nil; see #71844.
// Replace loop and make(...) as maps.Clone(src) returns map[int]string
// which is assignable to M.
var dst M
dst = make(M, len(src))
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
println(dst)
}
func useClone_generic[Map ~map[K]V, K comparable, V any](src Map) {
// Clone is tempting but wrong when src may be nil; see #71844.
// Replace loop and make(...) by maps.Clone
dst := make(Map, len(src))
// want "Replace m\\[k\\]=v loop with maps.Copy"
maps.Copy(dst, src)
println(dst)
}
// -- src is iter.Seq2 --
func useInsert_assignableToSeq2(dst map[int]string, src func(yield func(int, string) bool)) {
// Replace loop by maps.Insert because src is assignable to iter.Seq2.
// want "Replace m\\[k\\]=v loop with maps.Insert"
maps.Insert(dst, src)
}
func useCollect(src iter.Seq2[int, string]) {
// Replace loop and make(...) by maps.Collect.
var dst map[int]string
// A
// B
// C
// want "Replace m\\[k\\]=v loop with maps.Collect"
dst = maps.Collect(src)
}
func useInsert_typesDifferAssign(src iter.Seq2[int, string]) {
// Replace loop and make(...): maps.Collect returns an unnamed map type
// that is assignable to M.
var dst M
// A
// B
// want "Replace m\\[k\\]=v loop with maps.Collect"
dst = maps.Collect(src)
}
func useInsert_typesDifferDeclare(src iter.Seq2[int, string]) {
// Replace loop but not make(...) as maps.Collect would return an
// unnamed map type that would change the type of dst.
dst := make(M)
// want "Replace m\\[k\\]=v loop with maps.Insert"
maps.Insert(dst, src)
}
// -- non-matches --
type isomerOfSeq2 func(yield func(int, string) bool)
func nopeInsertRequiresAssignableToSeq2(dst map[int]string, src isomerOfSeq2) {
for k, v := range src { // nope: src is not assignable to maps.Insert's iter.Seq2 parameter
dst[k] = v
}
}
func nopeSingleVarRange(dst map[int]bool, src map[int]string) {
for key := range src { // nope: must be "for k, v"
dst[key] = true
}
}
func nopeBodyNotASingleton(src map[int]string) {
var dst map[int]string
for key, value := range src {
dst[key] = value
println() // nope: other things in the loop body
}
}
// Regression test for https://github.com/golang/go/issues/70815#issuecomment-2581999787.
func nopeAssignmentHasIncrementOperator(src map[int]int) {
dst := make(map[int]int)
for k, v := range src {
dst[k] += v
}
}
func nopeNotAMap(src map[int]string) {
var dst []string
for k, v := range src {
dst[k] = v
}
}
func nopeNotAMapGeneric[E any, M ~map[int]E, S ~[]E](src M) {
var dst S
for k, v := range src {
dst[k] = v
}
}
func nopeHasImplicitWidening(src map[string]int) {
dst := make(map[string]any)
for k, v := range src {
dst[k] = v
}
}