x/mod: apply go fix and go vet

(Needed so that I can vendor this into std,
a consequence of vendoring x/tools into std.)

A number of places were further simplified by hand.

Change-Id: Ic836afb1623365edcf81f5363f213366a2978d28
Reviewed-on: https://go-review.googlesource.com/c/mod/+/720581
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Auto-Submit: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/modfile/print.go b/modfile/print.go
index 2a0123d..48dbd82 100644
--- a/modfile/print.go
+++ b/modfile/print.go
@@ -33,7 +33,7 @@
 }
 
 // printf prints to the buffer.
-func (p *printer) printf(format string, args ...interface{}) {
+func (p *printer) printf(format string, args ...any) {
 	fmt.Fprintf(p, format, args...)
 }
 
diff --git a/modfile/read.go b/modfile/read.go
index f58de02..504a2f1 100644
--- a/modfile/read.go
+++ b/modfile/read.go
@@ -600,7 +600,7 @@
 
 	// Checked all punctuation. Must be identifier token.
 	if c := in.peekRune(); !isIdent(c) {
-		in.Error(fmt.Sprintf("unexpected input character %#q", c))
+		in.Error(fmt.Sprintf("unexpected input character %#q", rune(c)))
 	}
 
 	// Scan over identifier.
diff --git a/modfile/read_test.go b/modfile/read_test.go
index 8bf05e2..10759f6 100644
--- a/modfile/read_test.go
+++ b/modfile/read_test.go
@@ -29,7 +29,6 @@
 		t.Fatal(err)
 	}
 	for _, out := range outs {
-		out := out
 		name := strings.TrimSuffix(filepath.Base(out), ".golden")
 		t.Run(name, func(t *testing.T) {
 			t.Parallel()
@@ -149,7 +148,6 @@
 		t.Fatal(err)
 	}
 	for _, out := range outs {
-		out := out
 		name := filepath.Base(out)
 		if !strings.HasSuffix(out, ".in") && !strings.HasSuffix(out, ".golden") {
 			continue
@@ -216,8 +214,8 @@
 				ndata = ndata2
 			}
 
-			if strings.HasSuffix(out, ".in") {
-				golden, err := os.ReadFile(strings.TrimSuffix(out, ".in") + ".golden")
+			if before, ok := strings.CutSuffix(out, ".in"); ok {
+				golden, err := os.ReadFile(before + ".golden")
 				if err != nil {
 					t.Fatal(err)
 				}
@@ -239,14 +237,14 @@
 
 // errorf returns an error described by the printf-style format and arguments,
 // inserting the current file position before the error text.
-func (eq *eqchecker) errorf(format string, args ...interface{}) error {
+func (eq *eqchecker) errorf(format string, args ...any) error {
 	return fmt.Errorf("%s:%d: %s", eq.file, eq.pos.Line,
 		fmt.Sprintf(format, args...))
 }
 
 // check checks that v and w represent the same parse tree.
 // If not, it returns an error describing the first difference.
-func (eq *eqchecker) check(v, w interface{}) error {
+func (eq *eqchecker) check(v, w any) error {
 	return eq.checkValue(reflect.ValueOf(v), reflect.ValueOf(w))
 }
 
@@ -322,7 +320,7 @@
 		// Fields in struct must match.
 		t := v.Type()
 		n := t.NumField()
-		for i := 0; i < n; i++ {
+		for i := range n {
 			tf := t.Field(i)
 			switch {
 			default:
@@ -335,7 +333,7 @@
 			}
 		}
 
-	case reflect.Ptr, reflect.Interface:
+	case reflect.Pointer, reflect.Interface:
 		if v.IsNil() != w.IsNil() {
 			if v.IsNil() {
 				return eq.errorf("unexpected %s", w.Elem().Type())
diff --git a/modfile/rule.go b/modfile/rule.go
index a86ee4f..c5b8305 100644
--- a/modfile/rule.go
+++ b/modfile/rule.go
@@ -368,7 +368,7 @@
 			Err:      err,
 		})
 	}
-	errorf := func(format string, args ...interface{}) {
+	errorf := func(format string, args ...any) {
 		wrapError(fmt.Errorf(format, args...))
 	}
 
@@ -574,7 +574,7 @@
 			Err:      err,
 		}
 	}
-	errorf := func(format string, args ...interface{}) *Error {
+	errorf := func(format string, args ...any) *Error {
 		return wrapError(fmt.Errorf(format, args...))
 	}
 
@@ -685,7 +685,7 @@
 			Err:      err,
 		})
 	}
-	errorf := func(format string, args ...interface{}) {
+	errorf := func(format string, args ...any) {
 		wrapError(fmt.Errorf(format, args...))
 	}
 
@@ -1594,7 +1594,7 @@
 		r.Syntax = f.Syntax.addLine(nil, "retract", "[", AutoQuote(vi.Low), ",", AutoQuote(vi.High), "]")
 	}
 	if rationale != "" {
-		for _, line := range strings.Split(rationale, "\n") {
+		for line := range strings.SplitSeq(rationale, "\n") {
 			com := Comment{Token: "// " + line}
 			r.Syntax.Comment().Before = append(r.Syntax.Comment().Before, com)
 		}
diff --git a/modfile/work_test.go b/modfile/work_test.go
index b4b4e7e..a450a2b 100644
--- a/modfile/work_test.go
+++ b/modfile/work_test.go
@@ -389,7 +389,6 @@
 		t.Fatal(err)
 	}
 	for _, out := range outs {
-		out := out
 		name := filepath.Base(out)
 		t.Run(name, func(t *testing.T) {
 			t.Parallel()
@@ -441,8 +440,8 @@
 				ndata = ndata2
 			}
 
-			if strings.HasSuffix(out, ".in") {
-				golden, err := os.ReadFile(strings.TrimSuffix(out, ".in") + ".golden")
+			if before, ok := strings.CutSuffix(out, ".in"); ok {
+				golden, err := os.ReadFile(before + ".golden")
 				if err != nil {
 					t.Fatal(err)
 				}
diff --git a/module/module.go b/module/module.go
index 9d3955b..739c13f 100644
--- a/module/module.go
+++ b/module/module.go
@@ -802,8 +802,8 @@
 	for globs != "" {
 		// Extract next non-empty glob in comma-separated list.
 		var glob string
-		if i := strings.Index(globs, ","); i >= 0 {
-			glob, globs = globs[:i], globs[i+1:]
+		if before, after, ok := strings.Cut(globs, ","); ok {
+			glob, globs = before, after
 		} else {
 			glob, globs = globs, ""
 		}
diff --git a/semver/semver_test.go b/semver/semver_test.go
index 56739ad..2b92d09 100644
--- a/semver/semver_test.go
+++ b/semver/semver_test.go
@@ -228,7 +228,7 @@
 )
 
 func BenchmarkCompare(b *testing.B) {
-	for i := 0; i < b.N; i++ {
+	for b.Loop() {
 		if Compare(v1, v2) != 0 {
 			b.Fatalf("bad compare")
 		}
diff --git a/sumdb/cache.go b/sumdb/cache.go
index 629e591..749a80d 100644
--- a/sumdb/cache.go
+++ b/sumdb/cache.go
@@ -20,13 +20,13 @@
 type cacheEntry struct {
 	done   uint32
 	mu     sync.Mutex
-	result interface{}
+	result any
 }
 
 // Do calls the function f if and only if Do is being called for the first time with this key.
 // No call to Do with a given key returns until the one call to f returns.
 // Do returns the value returned by the one call to f.
-func (c *parCache) Do(key interface{}, f func() interface{}) interface{} {
+func (c *parCache) Do(key any, f func() any) any {
 	entryIface, ok := c.m.Load(key)
 	if !ok {
 		entryIface, _ = c.m.LoadOrStore(key, new(cacheEntry))
@@ -46,7 +46,7 @@
 // Get returns the cached result associated with key.
 // It returns nil if there is no such result.
 // If the result for key is being computed, Get does not wait for the computation to finish.
-func (c *parCache) Get(key interface{}) interface{} {
+func (c *parCache) Get(key any) any {
 	entryIface, ok := c.m.Load(key)
 	if !ok {
 		return nil
diff --git a/sumdb/client.go b/sumdb/client.go
index 04dbdfe..f926eda 100644
--- a/sumdb/client.go
+++ b/sumdb/client.go
@@ -244,7 +244,7 @@
 		data []byte
 		err  error
 	}
-	result := c.record.Do(file, func() interface{} {
+	result := c.record.Do(file, func() any {
 		// Try the on-disk cache, or else get from web.
 		writeCache := false
 		data, err := c.ops.ReadCache(file)
@@ -284,7 +284,7 @@
 	// (with or without /go.mod).
 	prefix := path + " " + vers + " "
 	var hashes []string
-	for _, line := range strings.Split(string(result.data), "\n") {
+	for line := range strings.SplitSeq(string(result.data), "\n") {
 		if strings.HasPrefix(line, prefix) {
 			hashes = append(hashes, line)
 		}
@@ -552,7 +552,7 @@
 		err  error
 	}
 
-	result := c.tileCache.Do(tile, func() interface{} {
+	result := c.tileCache.Do(tile, func() any {
 		// Try the requested tile in on-disk cache.
 		data, err := c.ops.ReadCache(c.tileCacheKey(tile))
 		if err == nil {
diff --git a/sumdb/client_test.go b/sumdb/client_test.go
index 0f3c481..f085e7d 100644
--- a/sumdb/client_test.go
+++ b/sumdb/client_test.go
@@ -7,6 +7,7 @@
 import (
 	"bytes"
 	"fmt"
+	"maps"
 	"strings"
 	"sync"
 	"testing"
@@ -311,22 +312,14 @@
 		treeSize:   tc.treeSize,
 		hashes:     append([]tlog.Hash{}, tc.hashes...),
 		signer:     tc.signer,
-		config:     copyMap(tc.config),
-		cache:      copyMap(tc.cache),
-		remote:     copyMap(tc.remote),
+		config:     maps.Clone(tc.config),
+		cache:      maps.Clone(tc.cache),
+		remote:     maps.Clone(tc.remote),
 	}
 	tc2.newClient()
 	return tc2
 }
 
-func copyMap(m map[string][]byte) map[string][]byte {
-	m2 := make(map[string][]byte)
-	for k, v := range m {
-		m2[k] = v
-	}
-	return m2
-}
-
 // ReadHashes is tc's implementation of tlog.HashReader, for use with
 // tlog.TreeHash and so on.
 func (tc *testClient) ReadHashes(indexes []int64) ([]tlog.Hash, error) {
diff --git a/sumdb/note/note.go b/sumdb/note/note.go
index db9865c..8b2b252 100644
--- a/sumdb/note/note.go
+++ b/sumdb/note/note.go
@@ -240,8 +240,8 @@
 
 // NewVerifier construct a new [Verifier] from an encoded verifier key.
 func NewVerifier(vkey string) (Verifier, error) {
-	name, vkey := chop(vkey, "+")
-	hash16, key64 := chop(vkey, "+")
+	name, vkey, _ := strings.Cut(vkey, "+")
+	hash16, key64, _ := strings.Cut(vkey, "+")
 	hash, err1 := strconv.ParseUint(hash16, 16, 32)
 	key, err2 := base64.StdEncoding.DecodeString(key64)
 	if len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
@@ -276,12 +276,8 @@
 // chop chops s at the first instance of sep, if any,
 // and returns the text before and after sep.
 // If sep is not present, chop returns before is s and after is empty.
-func chop(s, sep string) (before, after string) {
-	i := strings.Index(s, sep)
-	if i < 0 {
-		return s, ""
-	}
-	return s[:i], s[i+len(sep):]
+func chop(s, sep string) (before, after string, ok bool) {
+	return strings.Cut(s, sep)
 }
 
 // verifier is a trivial Verifier implementation.
@@ -297,10 +293,10 @@
 
 // NewSigner constructs a new [Signer] from an encoded signer key.
 func NewSigner(skey string) (Signer, error) {
-	priv1, skey := chop(skey, "+")
-	priv2, skey := chop(skey, "+")
-	name, skey := chop(skey, "+")
-	hash16, key64 := chop(skey, "+")
+	priv1, skey, _ := strings.Cut(skey, "+")
+	priv2, skey, _ := strings.Cut(skey, "+")
+	name, skey, _ := strings.Cut(skey, "+")
+	hash16, key64, _ := strings.Cut(skey, "+")
 	hash, err1 := strconv.ParseUint(hash16, 16, 32)
 	key, err2 := base64.StdEncoding.DecodeString(key64)
 	if priv1 != "PRIVATE" || priv2 != "KEY" || len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
@@ -557,7 +553,7 @@
 			return nil, errMalformedNote
 		}
 		line = line[len(sigPrefix):]
-		name, b64 := chop(string(line), " ")
+		name, b64, _ := chop(string(line), " ")
 		sig, err := base64.StdEncoding.DecodeString(b64)
 		if err != nil || !isValidName(name) || b64 == "" || len(sig) < 5 {
 			return nil, errMalformedNote
diff --git a/sumdb/note/note_test.go b/sumdb/note/note_test.go
index 75ef3a1..22267e7 100644
--- a/sumdb/note/note_test.go
+++ b/sumdb/note/note_test.go
@@ -36,7 +36,7 @@
 			}
 		}
 	}
-	for i := 0; i < len(b); i++ {
+	for i := range b {
 		b[i]++
 		badKey(string(b))
 		b[i]--
@@ -66,7 +66,7 @@
 			}
 		}
 	}
-	for i := 0; i < len(b); i++ {
+	for i := range b {
 		b[i]++
 		_, err := NewSigner(string(b))
 		if err == nil {
diff --git a/sumdb/server.go b/sumdb/server.go
index 216a256..2433c93 100644
--- a/sumdb/server.go
+++ b/sumdb/server.go
@@ -76,8 +76,7 @@
 			http.Error(w, "invalid module@version syntax", http.StatusBadRequest)
 			return
 		}
-		i := strings.Index(mod, "@")
-		escPath, escVers := mod[:i], mod[i+1:]
+		escPath, escVers, _ := strings.Cut(mod, "@")
 		path, err := module.UnescapePath(escPath)
 		if err != nil {
 			reportError(w, err)
diff --git a/sumdb/storage/test.go b/sumdb/storage/test.go
index fdf410e..07309f8 100644
--- a/sumdb/storage/test.go
+++ b/sumdb/storage/test.go
@@ -17,7 +17,7 @@
 
 	// Insert records.
 	err := s.ReadWrite(ctx, func(ctx context.Context, tx Transaction) error {
-		for i := 0; i < 10; i++ {
+		for i := range 10 {
 			err := tx.BufferWrites([]Write{
 				{Key: fmt.Sprint(i), Value: fmt.Sprint(-i)},
 				{Key: fmt.Sprint(1000 + i), Value: fmt.Sprint(-1000 - i)},
diff --git a/sumdb/test.go b/sumdb/test.go
index fb77245..0868bef 100644
--- a/sumdb/test.go
+++ b/sumdb/test.go
@@ -66,7 +66,7 @@
 	defer s.mu.Unlock()
 
 	var list [][]byte
-	for i := int64(0); i < n; i++ {
+	for i := range n {
 		if id+i >= int64(len(s.records)) {
 			return nil, fmt.Errorf("missing records")
 		}
diff --git a/sumdb/tlog/ct_test.go b/sumdb/tlog/ct_test.go
index f8c364b..0f6183a 100644
--- a/sumdb/tlog/ct_test.go
+++ b/sumdb/tlog/ct_test.go
@@ -70,7 +70,7 @@
 	Proof TreeProof `json:"consistency"`
 }
 
-func httpGET(t *testing.T, url string, targ interface{}) {
+func httpGET(t *testing.T, url string, targ any) {
 	if testing.Verbose() {
 		println()
 		println(url)
diff --git a/sumdb/tlog/note.go b/sumdb/tlog/note.go
index fc6d5fa..1ea765a 100644
--- a/sumdb/tlog/note.go
+++ b/sumdb/tlog/note.go
@@ -35,7 +35,7 @@
 // A future backwards-incompatible encoding would use a different
 // first line (for example, "go.sum database tree v2").
 func FormatTree(tree Tree) []byte {
-	return []byte(fmt.Sprintf("go.sum database tree\n%d\n%s\n", tree.N, tree.Hash))
+	return fmt.Appendf(nil, "go.sum database tree\n%d\n%s\n", tree.N, tree.Hash)
 }
 
 var errMalformedTree = errors.New("malformed tree note")
@@ -87,7 +87,7 @@
 	if !isValidRecordText(text) {
 		return nil, errMalformedRecord
 	}
-	msg = []byte(fmt.Sprintf("%d\n", id))
+	msg = fmt.Appendf(nil, "%d\n", id)
 	msg = append(msg, text...)
 	msg = append(msg, '\n')
 	return msg, nil
diff --git a/sumdb/tlog/tlog.go b/sumdb/tlog/tlog.go
index f7ea753..480b5ef 100644
--- a/sumdb/tlog/tlog.go
+++ b/sumdb/tlog/tlog.go
@@ -194,7 +194,7 @@
 	// and consumes a hash from an adjacent subtree.
 	m := int(bits.TrailingZeros64(uint64(n + 1)))
 	indexes := make([]int64, m)
-	for i := 0; i < m; i++ {
+	for i := range m {
 		// We arrange indexes in sorted order.
 		// Note that n>>i is always odd.
 		indexes[m-1-i] = StoredHashIndex(i, n>>uint(i)-1)
@@ -210,7 +210,7 @@
 	}
 
 	// Build new hashes.
-	for i := 0; i < m; i++ {
+	for i := range m {
 		h = NodeHash(old[m-1-i], h)
 		hashes = append(hashes, h)
 	}
diff --git a/sumdb/tlog/tlog_test.go b/sumdb/tlog/tlog_test.go
index 79db244..cce800e 100644
--- a/sumdb/tlog/tlog_test.go
+++ b/sumdb/tlog/tlog_test.go
@@ -62,8 +62,8 @@
 	var storage testHashStorage
 	tiles := make(map[Tile][]byte)
 	const testH = 2
-	for i := int64(0); i < 100; i++ {
-		data := []byte(fmt.Sprintf("leaf %d", i))
+	for i := range int64(100) {
+		data := fmt.Appendf(nil, "leaf %d", i)
 		hashes, err := StoredHashes(i, data, storage)
 		if err != nil {
 			t.Fatal(err)
@@ -218,8 +218,8 @@
 }
 
 func TestSplitStoredHashIndex(t *testing.T) {
-	for l := 0; l < 10; l++ {
-		for n := int64(0); n < 100; n++ {
+	for l := range 10 {
+		for n := range int64(100) {
 			x := StoredHashIndex(l, n)
 			l1, n1 := SplitStoredHashIndex(x)
 			if l1 != l || n1 != n {
diff --git a/zip/zip.go b/zip/zip.go
index 3673db4..48363ce 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -780,7 +780,7 @@
 func (fi dataFileInfo) Mode() os.FileMode  { return 0644 }
 func (fi dataFileInfo) ModTime() time.Time { return time.Time{} }
 func (fi dataFileInfo) IsDir() bool        { return false }
-func (fi dataFileInfo) Sys() interface{}   { return nil }
+func (fi dataFileInfo) Sys() any           { return nil }
 
 // isVendoredPackage attempts to report whether the given filename is contained
 // in a package whose import path contains (but does not end with) the component
diff --git a/zip/zip_test.go b/zip/zip_test.go
index 106df80..5c55973 100644
--- a/zip/zip_test.go
+++ b/zip/zip_test.go
@@ -98,11 +98,11 @@
 		if line == "" {
 			continue
 		}
-		eq := strings.IndexByte(line, '=')
-		if eq < 0 {
+		before, after, ok := strings.Cut(line, "=")
+		if !ok {
 			return testParams{}, fmt.Errorf("%s:%d: missing = separator", file, n)
 		}
-		key, value := strings.TrimSpace(line[:eq]), strings.TrimSpace(line[eq+1:])
+		key, value := strings.TrimSpace(before), strings.TrimSpace(after)
 		switch key {
 		case "path":
 			test.path = value
@@ -190,7 +190,7 @@
 func (fi fakeFileInfo) Mode() os.FileMode  { return 0644 }
 func (fi fakeFileInfo) ModTime() time.Time { return time.Time{} }
 func (fi fakeFileInfo) IsDir() bool        { return false }
-func (fi fakeFileInfo) Sys() interface{}   { return nil }
+func (fi fakeFileInfo) Sys() any           { return nil }
 
 type zeroReader struct{}
 
@@ -228,7 +228,6 @@
 		t.Fatal(err)
 	}
 	for _, testPath := range testPaths {
-		testPath := testPath
 		name := strings.TrimSuffix(filepath.Base(testPath), ".txt")
 		t.Run(name, func(t *testing.T) {
 			t.Parallel()
@@ -285,7 +284,6 @@
 		t.Fatal(err)
 	}
 	for _, testPath := range testPaths {
-		testPath := testPath
 		name := strings.TrimSuffix(filepath.Base(testPath), ".txt")
 		t.Run(name, func(t *testing.T) {
 			t.Parallel()
@@ -345,7 +343,6 @@
 		t.Fatal(err)
 	}
 	for _, testPath := range testPaths {
-		testPath := testPath
 		name := strings.TrimSuffix(filepath.Base(testPath), ".txt")
 		t.Run(name, func(t *testing.T) {
 			t.Parallel()
@@ -403,7 +400,6 @@
 		t.Fatal(err)
 	}
 	for _, testEntry := range testEntries {
-		testEntry := testEntry
 		base := filepath.Base(testEntry.Name())
 		if filepath.Ext(base) != ".txt" {
 			continue
@@ -466,7 +462,6 @@
 		t.Fatal(err)
 	}
 	for _, testEntry := range testEntries {
-		testEntry := testEntry
 		base := filepath.Base(testEntry.Name())
 		if filepath.Ext(base) != ".txt" {
 			continue
@@ -752,7 +747,6 @@
 	})
 
 	for _, test := range tests {
-		test := test
 		t.Run(test.desc, func(t *testing.T) {
 			t.Parallel()
 
@@ -788,7 +782,6 @@
 		t.Skip("creating large files takes time")
 	}
 	for _, test := range sizeLimitTests {
-		test := test
 		t.Run(test.desc, func(t *testing.T) {
 			t.Parallel()
 			tmpZipFile, err := os.CreateTemp(t.TempDir(), "TestUnzipSizeLimits-*.zip")
@@ -939,7 +932,6 @@
 			wantErr2: "not a valid zip file",
 		},
 	} {
-		test := test
 		t.Run(test.desc, func(t *testing.T) {
 			t.Parallel()
 			tmpZipFile, err := os.CreateTemp(t.TempDir(), "TestUnzipSizeLimitsSpecial-*.zip")
@@ -1198,7 +1190,6 @@
 			wantZipHash:     "d6a7e03e02e5f7714bd12653d319a3b0f6e1099c01b1f9a17bc3613fb31c9170",
 		},
 	} {
-		test := test
 		testName := strings.ReplaceAll(test.m.String(), "/", "_")
 		t.Run(testName, func(t *testing.T) {
 			if have, ok := haveVCS[test.vcs]; !ok {