golang / golang/go

x/tools/go/analysis/passes/modernize: mapsloop should use `maps.Clone` when it can prove the operand is non-nil

Open
#75,845 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

FeatureRequest gopls Tools
Dominant language
Go
Stars
139k
Forks
19.9k
PR merge metrics
PR metrics pending

Description

gopls version

binary compiled by latest code

go env
AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN='/Users/mac/go/bin'
GOCACHE='/Users/mac/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/mac/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/tq/m955dwkd1519phkp2hwpv9_80000gn/T/go-build2400307511=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/Users/mac/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/mac/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/mac/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.24.3'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?

For the following code:

package main

import (
	"fmt"
	"maps"
)

var fruitProperties = map[string][]string{
	"apple":  {"red", "sweet", "crispy"},
	"banana": {"yellow", "soft", "tropical"},
	"orange": {"orange", "citrus", "juicy"},
	"grape":  {"purple", "small", "sweet"},
}

func GetFruitPropertiesOld() map[string][]string {
	dupProperties := make(map[string][]string)
	for k, v := range fruitProperties {
		dupProperties[k] = v
	}
	return dupProperties
}

func GetFruitPropertiesNew() map[string][]string {
	return maps.Clone(fruitProperties)
}

func main() {
	oldCopy := GetFruitPropertiesOld()
	fmt.Println(oldCopy)

	newCopy := GetFruitPropertiesNew()
	fmt.Println(newCopy)

	newCopy["apple"] = []string{"green", "sour"}

	fmt.Println("original map:", fruitProperties["apple"])
	fmt.Println("new clone map:", newCopy["apple"])
}

What did you see happen?

After being processed by the modernize analyzer, it will be transformed into the following

package main

import (
	"fmt"
	"maps"
)

var fruitProperties = map[string][]string{
	"apple":  {"red", "sweet", "crispy"},
	"banana": {"yellow", "soft", "tropical"},
	"orange": {"orange", "citrus", "juicy"},
	"grape":  {"purple", "small", "sweet"},
}

func GetFruitPropertiesOld() map[string][]string {
	dupProperties := make(map[string][]string)
	maps.Copy(dupProperties, fruitProperties)
	return dupProperties
}

func GetFruitPropertiesNew() map[string][]string {
	return maps.Clone(fruitProperties)
}

func main() {
	oldCopy := GetFruitPropertiesOld()
	fmt.Println(oldCopy)

	newCopy := GetFruitPropertiesNew()
	fmt.Println(newCopy)

	newCopy["apple"] = []string{"green", "sour"}

	fmt.Println("original map:", fruitProperties["apple"])
	fmt.Println("new clone map:", newCopy["apple"])
}
What did you expect to see?

It is better to use maps.Clone than maps.Copy here. Just like GetFruitPropertiesNew

Editor and settings

No response

Logs

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in x/tools/go/analysis/passes/modernize, focusing on the mapsloop analyzer and its existing tests. Compare the reported maps.Copy transformation with the non-nil operand example, then add coverage showing that eligible loops are transformed to maps.Clone while other cases retain their current behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.