`$GOROOT/bin/go` should install a symlink instead of relocating
or copying the `go` binary.
+### Vet {#vet}
+
+The `go vet` subcommand now includes the
+[stdversion](https://beta.pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdversion)
+analyzer, which flags references to symbols that are too new for the version
+of Go in effect in the referring file. (The effective version is determined
+by the `go` directive in the file's enclosing `go.mod` file, and
+by any [`//go:build` constraints](https://pkg.go.dev/cmd/go#hdr-Build_constraints)
+in the file.)
+
+For example, it will report a diagnostic for a reference to the
+`reflect.TypeFor` function (introduced in go1.22) from a file in a
+module whose go.mod file specifies `go 1.21`.
+
### Cgo {#cgo}
"golang.org/x/tools/go/analysis/passes/sigchanyzer"
"golang.org/x/tools/go/analysis/passes/slog"
"golang.org/x/tools/go/analysis/passes/stdmethods"
+ "golang.org/x/tools/go/analysis/passes/stdversion"
"golang.org/x/tools/go/analysis/passes/stringintconv"
"golang.org/x/tools/go/analysis/passes/structtag"
"golang.org/x/tools/go/analysis/passes/testinggoroutine"
sigchanyzer.Analyzer,
slog.Analyzer,
stdmethods.Analyzer,
+ stdversion.Analyzer,
stringintconv.Analyzer,
structtag.Analyzer,
tests.Analyzer,
t.Log("vet stderr:\n", cmd.Stderr)
}
})
+
+ // The stdversion analyzer requires a lower-than-tip go
+ // version in its go.mod file for it to report anything.
+ // So again we use a testdata go.mod file to "downgrade".
+ t.Run("stdversion", func(t *testing.T) {
+ cmd := testenv.Command(t, testenv.GoToolPath(t), "vet", "-vettool="+vetPath(t), ".")
+ cmd.Env = append(os.Environ(), "GOWORK=off")
+ cmd.Dir = "testdata/stdversion"
+ cmd.Stderr = new(strings.Builder) // all vet output goes to stderr
+ cmd.Run()
+ stderr := cmd.Stderr.(fmt.Stringer).String()
+
+ filename := filepath.FromSlash("testdata/stdversion/stdversion.go")
+
+ // Unlike the tests above, which runs vet in cmd/vet/, this one
+ // runs it in subdirectory, so the "full names" in the output
+ // are in fact short "./rangeloop.go".
+ // But we can't just pass "./rangeloop.go" as the "full name"
+ // argument to errorCheck as it does double duty as both a
+ // string that appears in the output, and as file name
+ // openable relative to the test directory, containing text
+ // expectations.
+ //
+ // So, we munge the file.
+ stderr = strings.ReplaceAll(stderr, filepath.FromSlash("./stdversion.go"), filename)
+
+ if err := errorCheck(stderr, false, filename, filepath.Base(filename)); err != nil {
+ t.Errorf("error check failed: %s", err)
+ t.Log("vet stderr:\n", cmd.Stderr)
+ }
+ })
}
func cgoEnabled(t *testing.T) bool {