Skip to content

Commit 4ba5527

Browse files
cmd/vet: make vetx output deterministic
The vetx output file is a build output, and as such should be deterministic. This CL changes it to not depend on map iteration order. This avoids a pointless GODEBUG=gocacheverify=1 failure. Updates #25666 Change-Id: Ic132bad134cb10938275f883c2c68432cb7c4409 Reviewed-on: https://go-review.googlesource.com/121941 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Rob Pike <[email protected]>
1 parent 3f54e85 commit 4ba5527

File tree

2 files changed

+55
-8
lines changed

2 files changed

+55
-8
lines changed

src/cmd/vet/main.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"io/ioutil"
2525
"os"
2626
"path/filepath"
27+
"sort"
2728
"strconv"
2829
"strings"
2930

@@ -163,6 +164,12 @@ var (
163164
exporters = make(map[string]func() interface{})
164165
)
165166

167+
// The exporters data as written to the vetx output file.
168+
type vetxExport struct {
169+
Name string
170+
Data interface{}
171+
}
172+
166173
// Vet can provide its own "export information"
167174
// about package A to future invocations of vet
168175
// on packages importing A. If B imports A,
@@ -399,10 +406,17 @@ func doPackageCfg(cfgFile string) {
399406
mustTypecheck = true
400407
doPackage(vcfg.GoFiles, nil)
401408
if vcfg.VetxOutput != "" {
402-
out := make(map[string]interface{})
409+
out := make([]vetxExport, 0, len(exporters))
403410
for name, fn := range exporters {
404-
out[name] = fn()
411+
out = append(out, vetxExport{
412+
Name: name,
413+
Data: fn(),
414+
})
405415
}
416+
// Sort the data so that it is consistent across builds.
417+
sort.Slice(out, func(i, j int) bool {
418+
return out[i].Name < out[j].Name
419+
})
406420
var buf bytes.Buffer
407421
if err := gob.NewEncoder(&buf).Encode(out); err != nil {
408422
errorf("encoding vet output: %v", err)
@@ -721,11 +735,15 @@ func readVetx(path, key string) interface{} {
721735
if err != nil {
722736
return nil
723737
}
724-
m = make(map[string]interface{})
725-
err = gob.NewDecoder(bytes.NewReader(data)).Decode(&m)
738+
var out []vetxExport
739+
err = gob.NewDecoder(bytes.NewReader(data)).Decode(&out)
726740
if err != nil {
727741
return nil
728742
}
743+
m = make(map[string]interface{})
744+
for _, x := range out {
745+
m[x.Name] = x.Data
746+
}
729747
imported[path] = m
730748
}
731749
return m[key]

src/cmd/vet/print.go

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"go/token"
1717
"go/types"
1818
"regexp"
19+
"sort"
1920
"strconv"
2021
"strings"
2122
"unicode/utf8"
@@ -30,7 +31,7 @@ func init() {
3031
funcDecl, callExpr)
3132
registerPkgCheck("printf", findPrintfLike)
3233
registerExport("printf", exportPrintfLike)
33-
gob.Register(map[string]int(nil))
34+
gob.Register([]printfExport(nil))
3435
}
3536

3637
func initPrintFlags() {
@@ -57,6 +58,15 @@ func initPrintFlags() {
5758

5859
var localPrintfLike = make(map[string]int)
5960

61+
type printfExport struct {
62+
Name string
63+
Kind int
64+
}
65+
66+
// printfImported maps from package name to the printf vet data
67+
// exported by that package.
68+
var printfImported = make(map[string]map[string]int)
69+
6070
type printfWrapper struct {
6171
name string
6272
fn *ast.FuncDecl
@@ -241,7 +251,17 @@ func checkPrintfFwd(pkg *Package, w *printfWrapper, call *ast.CallExpr, kind int
241251
}
242252

243253
func exportPrintfLike() interface{} {
244-
return localPrintfLike
254+
out := make([]printfExport, 0, len(localPrintfLike))
255+
for name, kind := range localPrintfLike {
256+
out = append(out, printfExport{
257+
Name: name,
258+
Kind: kind,
259+
})
260+
}
261+
sort.Slice(out, func(i, j int) bool {
262+
return out[i].Name < out[j].Name
263+
})
264+
return out
245265
}
246266

247267
// isPrint records the print functions.
@@ -438,9 +458,18 @@ func printfNameAndKind(pkg *Package, called ast.Expr) (pkgpath, name string, kin
438458

439459
if pkgpath == "" {
440460
kind = localPrintfLike[name]
461+
} else if m, ok := printfImported[pkgpath]; ok {
462+
kind = m[name]
441463
} else {
442-
printfLike, _ := readVetx(pkgpath, "printf").(map[string]int)
443-
kind = printfLike[name]
464+
var m map[string]int
465+
if out, ok := readVetx(pkgpath, "printf").([]printfExport); ok {
466+
m = make(map[string]int)
467+
for _, x := range out {
468+
m[x.Name] = x.Kind
469+
}
470+
}
471+
printfImported[pkgpath] = m
472+
kind = m[name]
444473
}
445474

446475
if kind == 0 {

0 commit comments

Comments
 (0)