]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/vet: add stdversion analyzer
authorAlan Donovan <adonovan@google.com>
Tue, 30 Apr 2024 20:21:20 +0000 (16:21 -0400)
committerAlan Donovan <adonovan@google.com>
Fri, 3 May 2024 01:02:40 +0000 (01:02 +0000)
+ release note, test

Fixes #46136

Change-Id: Ib157c5343dde379f8d6f67bdfa64b3f6a6432bab
Reviewed-on: https://go-review.googlesource.com/c/go/+/582556
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
doc/next/3-tools.md
src/cmd/go/internal/test/flagdefs.go
src/cmd/vet/main.go
src/cmd/vet/testdata/stdversion/go.mod [new file with mode: 0644]
src/cmd/vet/testdata/stdversion/stdversion.go [new file with mode: 0644]
src/cmd/vet/vet_test.go

index bdbe6c077173d05ac85cc18410702060400f51aa..c052f3b084009a98efb1101426c625da55ac9c30 100644 (file)
@@ -8,5 +8,19 @@ Distributions that install the `go` command to a location other than
 `$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}
 
index baa0cdf4c64d45f8e1cce4a3f8970d47b3aaf9ab..0292c19d821f367e1aaaaed8a2041b28a4f9fdf1 100644 (file)
@@ -67,6 +67,7 @@ var passAnalyzersToVet = map[string]bool{
        "sigchanyzer":      true,
        "slog":             true,
        "stdmethods":       true,
+       "stdversion":       true,
        "stringintconv":    true,
        "structtag":        true,
        "testinggoroutine": true,
index c5197284b56165159ffb942e35cf0ffcf0add9ce..7b9a700635d5afb8e7a5f628ca48302f792469ae 100644 (file)
@@ -32,6 +32,7 @@ import (
        "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"
@@ -70,6 +71,7 @@ func main() {
                sigchanyzer.Analyzer,
                slog.Analyzer,
                stdmethods.Analyzer,
+               stdversion.Analyzer,
                stringintconv.Analyzer,
                structtag.Analyzer,
                tests.Analyzer,
diff --git a/src/cmd/vet/testdata/stdversion/go.mod b/src/cmd/vet/testdata/stdversion/go.mod
new file mode 100644 (file)
index 0000000..90ae83b
--- /dev/null
@@ -0,0 +1,3 @@
+module stdversion
+
+go 1.21
diff --git a/src/cmd/vet/testdata/stdversion/stdversion.go b/src/cmd/vet/testdata/stdversion/stdversion.go
new file mode 100644 (file)
index 0000000..ba5846c
--- /dev/null
@@ -0,0 +1,5 @@
+package stdversion
+
+import "reflect"
+
+var _ = reflect.TypeFor[int]() // ERROR "reflect.TypeFor requires go1.22 or later \(module is go1.21\)"
index 278a88afb378b5590c5d288000ab8439d3dd86ee..ad42cf1d7c46d8256620cd0c9cebcc20ff432bad 100644 (file)
@@ -152,6 +152,37 @@ func TestVet(t *testing.T) {
                        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 {