Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: identify tool dependencies in go list / go mod why #70582

Open
seankhliao opened this issue Nov 26, 2024 · 9 comments
Open

cmd/go: identify tool dependencies in go list / go mod why #70582

seankhliao opened this issue Nov 26, 2024 · 9 comments
Labels
GoCommand cmd/go NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.

Comments

@seankhliao
Copy link
Member

Go version

go version devel go1.24-f8dba5f8c1 2024-11-23 01:01:47 +0000 linux/amd64

Output of go env in your module/workspace:

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='0'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v3'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/user/.cache/go-build'
GODEBUG=''
GOENV='/home/user/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS='-trimpath "-ldflags=-s -w" -vet=all'
GOGCCFLAGS='-fPIC -m64 -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build4089643650=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/user/code/mono/default/go.mod'
GOMODCACHE='/home/user/.data/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/user/.data/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/user/sdk/gotip'
GOSUMDB='sum.golang.org'
GOTELEMETRY='on'
GOTELEMETRYDIR='/home/user/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='path'
GOTOOLDIR='/home/user/sdk/gotip/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='devel go1.24-f8dba5f8c1 2024-11-23 01:01:47 +0000'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

go list -json honnef.co/go/tools/cmd/staticcheck
{
	"Dir": "/home/user/.data/go/pkg/mod/honnef.co/go/tools@v0.5.1/cmd/staticcheck",
	"ImportPath": "honnef.co/go/tools/cmd/staticcheck",
	"Name": "main",
	"Doc": "staticcheck analyses Go code and makes it better.",
	"Target": "/home/user/.data/go/bin/staticcheck",
	"Root": "/home/user/.data/go/pkg/mod/honnef.co/go/tools@v0.5.1",
	"Module": {
		"Path": "honnef.co/go/tools",
		"Version": "v0.5.1",
		"Time": "2024-08-14T20:27:15Z",
		"Indirect": true,
		"Dir": "/home/user/.data/go/pkg/mod/honnef.co/go/tools@v0.5.1",
		"GoMod": "/home/user/.data/go/pkg/mod/cache/download/honnef.co/go/tools/@v/v0.5.1.mod",
		"GoVersion": "1.22.1",
		"Sum": "h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=",
		"GoModSum": "h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs="
	},
	"Match": [
		"honnef.co/go/tools/cmd/staticcheck"
	],
	"Stale": true,
	"StaleReason": "stale dependency: internal/saferio",
	"GoFiles": [
		"staticcheck.go"
	],
	"Imports": [
		"honnef.co/go/tools/lintcmd",
		"honnef.co/go/tools/lintcmd/version",
		"honnef.co/go/tools/quickfix",
		"honnef.co/go/tools/simple",
		"honnef.co/go/tools/staticcheck",
		"honnef.co/go/tools/stylecheck",
		"honnef.co/go/tools/unused",
		"log",
		"os"
	],
	"Deps": [
		"bufio",
		"bytes",
		"cmp",
		"compress/flate",
		"compress/gzip",
		"compress/zlib",
		"container/heap",
		"container/list",
		"context",
		"crypto",
		"crypto/aes",
		"crypto/cipher",
		"crypto/des",
		"crypto/dsa",
		"crypto/ecdh",
		"crypto/ecdsa",
		"crypto/ed25519",
		"crypto/elliptic",
		"crypto/hmac",
		"crypto/internal/boring",
		"crypto/internal/boring/bbig",
		"crypto/internal/boring/sig",
		"crypto/internal/entropy",
		"crypto/internal/fips140",
		"crypto/internal/fips140/aes",
		"crypto/internal/fips140/aes/gcm",
		"crypto/internal/fips140/alias",
		"crypto/internal/fips140/bigmod",
		"crypto/internal/fips140/check",
		"crypto/internal/fips140/drbg",
		"crypto/internal/fips140/ecdh",
		"crypto/internal/fips140/ecdsa",
		"crypto/internal/fips140/ed25519",
		"crypto/internal/fips140/edwards25519",
		"crypto/internal/fips140/edwards25519/field",
		"crypto/internal/fips140/hkdf",
		"crypto/internal/fips140/hmac",
		"crypto/internal/fips140/mlkem",
		"crypto/internal/fips140/nistec",
		"crypto/internal/fips140/nistec/fiat",
		"crypto/internal/fips140/rsa",
		"crypto/internal/fips140/sha256",
		"crypto/internal/fips140/sha3",
		"crypto/internal/fips140/sha512",
		"crypto/internal/fips140/subtle",
		"crypto/internal/fips140/tls12",
		"crypto/internal/fips140/tls13",
		"crypto/internal/fips140deps/byteorder",
		"crypto/internal/fips140deps/cpu",
		"crypto/internal/fips140deps/godebug",
		"crypto/internal/fips140only",
		"crypto/internal/hpke",
		"crypto/internal/impl",
		"crypto/internal/randutil",
		"crypto/internal/sysrand",
		"crypto/md5",
		"crypto/rand",
		"crypto/rc4",
		"crypto/rsa",
		"crypto/sha1",
		"crypto/sha256",
		"crypto/sha512",
		"crypto/subtle",
		"crypto/tls",
		"crypto/tls/internal/fips140tls",
		"crypto/x509",
		"crypto/x509/pkix",
		"debug/dwarf",
		"debug/elf",
		"debug/macho",
		"encoding",
		"encoding/asn1",
		"encoding/base64",
		"encoding/binary",
		"encoding/gob",
		"encoding/hex",
		"encoding/json",
		"encoding/pem",
		"errors",
		"flag",
		"fmt",
		"github.com/BurntSushi/toml",
		"github.com/BurntSushi/toml/internal",
		"go/ast",
		"go/build",
		"go/build/constraint",
		"go/constant",
		"go/doc",
		"go/doc/comment",
		"go/format",
		"go/parser",
		"go/printer",
		"go/scanner",
		"go/token",
		"go/types",
		"go/version",
		"golang.org/x/exp/typeparams",
		"golang.org/x/mod/semver",
		"golang.org/x/sync/errgroup",
		"golang.org/x/tools/go/analysis",
		"golang.org/x/tools/go/analysis/passes/inspect",
		"golang.org/x/tools/go/ast/astutil",
		"golang.org/x/tools/go/ast/inspector",
		"golang.org/x/tools/go/buildutil",
		"golang.org/x/tools/go/gcexportdata",
		"golang.org/x/tools/go/internal/cgo",
		"golang.org/x/tools/go/loader",
		"golang.org/x/tools/go/packages",
		"golang.org/x/tools/go/types/objectpath",
		"golang.org/x/tools/go/types/typeutil",
		"golang.org/x/tools/internal/aliases",
		"golang.org/x/tools/internal/event",
		"golang.org/x/tools/internal/event/core",
		"golang.org/x/tools/internal/event/keys",
		"golang.org/x/tools/internal/event/label",
		"golang.org/x/tools/internal/gcimporter",
		"golang.org/x/tools/internal/gocommand",
		"golang.org/x/tools/internal/packagesinternal",
		"golang.org/x/tools/internal/pkgbits",
		"golang.org/x/tools/internal/stdlib",
		"golang.org/x/tools/internal/typeparams",
		"golang.org/x/tools/internal/typesinternal",
		"golang.org/x/tools/internal/versions",
		"hash",
		"hash/adler32",
		"hash/crc32",
		"honnef.co/go/tools/analysis/callcheck",
		"honnef.co/go/tools/analysis/code",
		"honnef.co/go/tools/analysis/edit",
		"honnef.co/go/tools/analysis/facts/deprecated",
		"honnef.co/go/tools/analysis/facts/directives",
		"honnef.co/go/tools/analysis/facts/generated",
		"honnef.co/go/tools/analysis/facts/nilness",
		"honnef.co/go/tools/analysis/facts/purity",
		"honnef.co/go/tools/analysis/facts/tokenfile",
		"honnef.co/go/tools/analysis/facts/typedness",
		"honnef.co/go/tools/analysis/lint",
		"honnef.co/go/tools/analysis/report",
		"honnef.co/go/tools/config",
		"honnef.co/go/tools/go/ast/astutil",
		"honnef.co/go/tools/go/buildid",
		"honnef.co/go/tools/go/ir",
		"honnef.co/go/tools/go/ir/irutil",
		"honnef.co/go/tools/go/loader",
		"honnef.co/go/tools/go/types/typeutil",
		"honnef.co/go/tools/internal/passes/buildir",
		"honnef.co/go/tools/internal/renameio",
		"honnef.co/go/tools/internal/robustio",
		"honnef.co/go/tools/internal/sharedcheck",
		"honnef.co/go/tools/internal/sync",
		"honnef.co/go/tools/knowledge",
		"honnef.co/go/tools/lintcmd",
		"honnef.co/go/tools/lintcmd/cache",
		"honnef.co/go/tools/lintcmd/runner",
		"honnef.co/go/tools/lintcmd/version",
		"honnef.co/go/tools/pattern",
		"honnef.co/go/tools/printf",
		"honnef.co/go/tools/quickfix",
		"honnef.co/go/tools/quickfix/qf1001",
		"honnef.co/go/tools/quickfix/qf1002",
		"honnef.co/go/tools/quickfix/qf1003",
		"honnef.co/go/tools/quickfix/qf1004",
		"honnef.co/go/tools/quickfix/qf1005",
		"honnef.co/go/tools/quickfix/qf1006",
		"honnef.co/go/tools/quickfix/qf1007",
		"honnef.co/go/tools/quickfix/qf1008",
		"honnef.co/go/tools/quickfix/qf1009",
		"honnef.co/go/tools/quickfix/qf1010",
		"honnef.co/go/tools/quickfix/qf1011",
		"honnef.co/go/tools/quickfix/qf1012",
		"honnef.co/go/tools/sarif",
		"honnef.co/go/tools/simple",
		"honnef.co/go/tools/simple/s1000",
		"honnef.co/go/tools/simple/s1001",
		"honnef.co/go/tools/simple/s1002",
		"honnef.co/go/tools/simple/s1003",
		"honnef.co/go/tools/simple/s1004",
		"honnef.co/go/tools/simple/s1005",
		"honnef.co/go/tools/simple/s1006",
		"honnef.co/go/tools/simple/s1007",
		"honnef.co/go/tools/simple/s1008",
		"honnef.co/go/tools/simple/s1009",
		"honnef.co/go/tools/simple/s1010",
		"honnef.co/go/tools/simple/s1011",
		"honnef.co/go/tools/simple/s1012",
		"honnef.co/go/tools/simple/s1016",
		"honnef.co/go/tools/simple/s1017",
		"honnef.co/go/tools/simple/s1018",
		"honnef.co/go/tools/simple/s1019",
		"honnef.co/go/tools/simple/s1020",
		"honnef.co/go/tools/simple/s1021",
		"honnef.co/go/tools/simple/s1023",
		"honnef.co/go/tools/simple/s1024",
		"honnef.co/go/tools/simple/s1025",
		"honnef.co/go/tools/simple/s1028",
		"honnef.co/go/tools/simple/s1029",
		"honnef.co/go/tools/simple/s1030",
		"honnef.co/go/tools/simple/s1031",
		"honnef.co/go/tools/simple/s1032",
		"honnef.co/go/tools/simple/s1033",
		"honnef.co/go/tools/simple/s1034",
		"honnef.co/go/tools/simple/s1035",
		"honnef.co/go/tools/simple/s1036",
		"honnef.co/go/tools/simple/s1037",
		"honnef.co/go/tools/simple/s1038",
		"honnef.co/go/tools/simple/s1039",
		"honnef.co/go/tools/simple/s1040",
		"honnef.co/go/tools/staticcheck",
		"honnef.co/go/tools/staticcheck/fakejson",
		"honnef.co/go/tools/staticcheck/fakereflect",
		"honnef.co/go/tools/staticcheck/fakexml",
		"honnef.co/go/tools/staticcheck/sa1000",
		"honnef.co/go/tools/staticcheck/sa1001",
		"honnef.co/go/tools/staticcheck/sa1002",
		"honnef.co/go/tools/staticcheck/sa1003",
		"honnef.co/go/tools/staticcheck/sa1004",
		"honnef.co/go/tools/staticcheck/sa1005",
		"honnef.co/go/tools/staticcheck/sa1006",
		"honnef.co/go/tools/staticcheck/sa1007",
		"honnef.co/go/tools/staticcheck/sa1008",
		"honnef.co/go/tools/staticcheck/sa1010",
		"honnef.co/go/tools/staticcheck/sa1011",
		"honnef.co/go/tools/staticcheck/sa1012",
		"honnef.co/go/tools/staticcheck/sa1013",
		"honnef.co/go/tools/staticcheck/sa1014",
		"honnef.co/go/tools/staticcheck/sa1015",
		"honnef.co/go/tools/staticcheck/sa1016",
		"honnef.co/go/tools/staticcheck/sa1017",
		"honnef.co/go/tools/staticcheck/sa1018",
		"honnef.co/go/tools/staticcheck/sa1019",
		"honnef.co/go/tools/staticcheck/sa1020",
		"honnef.co/go/tools/staticcheck/sa1021",
		"honnef.co/go/tools/staticcheck/sa1023",
		"honnef.co/go/tools/staticcheck/sa1024",
		"honnef.co/go/tools/staticcheck/sa1025",
		"honnef.co/go/tools/staticcheck/sa1026",
		"honnef.co/go/tools/staticcheck/sa1027",
		"honnef.co/go/tools/staticcheck/sa1028",
		"honnef.co/go/tools/staticcheck/sa1029",
		"honnef.co/go/tools/staticcheck/sa1030",
		"honnef.co/go/tools/staticcheck/sa1031",
		"honnef.co/go/tools/staticcheck/sa1032",
		"honnef.co/go/tools/staticcheck/sa2000",
		"honnef.co/go/tools/staticcheck/sa2001",
		"honnef.co/go/tools/staticcheck/sa2002",
		"honnef.co/go/tools/staticcheck/sa2003",
		"honnef.co/go/tools/staticcheck/sa3000",
		"honnef.co/go/tools/staticcheck/sa3001",
		"honnef.co/go/tools/staticcheck/sa4000",
		"honnef.co/go/tools/staticcheck/sa4001",
		"honnef.co/go/tools/staticcheck/sa4003",
		"honnef.co/go/tools/staticcheck/sa4004",
		"honnef.co/go/tools/staticcheck/sa4005",
		"honnef.co/go/tools/staticcheck/sa4006",
		"honnef.co/go/tools/staticcheck/sa4008",
		"honnef.co/go/tools/staticcheck/sa4009",
		"honnef.co/go/tools/staticcheck/sa4010",
		"honnef.co/go/tools/staticcheck/sa4011",
		"honnef.co/go/tools/staticcheck/sa4012",
		"honnef.co/go/tools/staticcheck/sa4013",
		"honnef.co/go/tools/staticcheck/sa4014",
		"honnef.co/go/tools/staticcheck/sa4015",
		"honnef.co/go/tools/staticcheck/sa4016",
		"honnef.co/go/tools/staticcheck/sa4017",
		"honnef.co/go/tools/staticcheck/sa4018",
		"honnef.co/go/tools/staticcheck/sa4019",
		"honnef.co/go/tools/staticcheck/sa4020",
		"honnef.co/go/tools/staticcheck/sa4021",
		"honnef.co/go/tools/staticcheck/sa4022",
		"honnef.co/go/tools/staticcheck/sa4023",
		"honnef.co/go/tools/staticcheck/sa4024",
		"honnef.co/go/tools/staticcheck/sa4025",
		"honnef.co/go/tools/staticcheck/sa4026",
		"honnef.co/go/tools/staticcheck/sa4027",
		"honnef.co/go/tools/staticcheck/sa4028",
		"honnef.co/go/tools/staticcheck/sa4029",
		"honnef.co/go/tools/staticcheck/sa4030",
		"honnef.co/go/tools/staticcheck/sa4031",
		"honnef.co/go/tools/staticcheck/sa4032",
		"honnef.co/go/tools/staticcheck/sa5000",
		"honnef.co/go/tools/staticcheck/sa5001",
		"honnef.co/go/tools/staticcheck/sa5002",
		"honnef.co/go/tools/staticcheck/sa5003",
		"honnef.co/go/tools/staticcheck/sa5004",
		"honnef.co/go/tools/staticcheck/sa5005",
		"honnef.co/go/tools/staticcheck/sa5007",
		"honnef.co/go/tools/staticcheck/sa5008",
		"honnef.co/go/tools/staticcheck/sa5009",
		"honnef.co/go/tools/staticcheck/sa5010",
		"honnef.co/go/tools/staticcheck/sa5011",
		"honnef.co/go/tools/staticcheck/sa5012",
		"honnef.co/go/tools/staticcheck/sa6000",
		"honnef.co/go/tools/staticcheck/sa6001",
		"honnef.co/go/tools/staticcheck/sa6002",
		"honnef.co/go/tools/staticcheck/sa6003",
		"honnef.co/go/tools/staticcheck/sa6005",
		"honnef.co/go/tools/staticcheck/sa6006",
		"honnef.co/go/tools/staticcheck/sa9001",
		"honnef.co/go/tools/staticcheck/sa9002",
		"honnef.co/go/tools/staticcheck/sa9003",
		"honnef.co/go/tools/staticcheck/sa9004",
		"honnef.co/go/tools/staticcheck/sa9005",
		"honnef.co/go/tools/staticcheck/sa9006",
		"honnef.co/go/tools/staticcheck/sa9007",
		"honnef.co/go/tools/staticcheck/sa9008",
		"honnef.co/go/tools/staticcheck/sa9009",
		"honnef.co/go/tools/stylecheck",
		"honnef.co/go/tools/stylecheck/st1000",
		"honnef.co/go/tools/stylecheck/st1001",
		"honnef.co/go/tools/stylecheck/st1003",
		"honnef.co/go/tools/stylecheck/st1005",
		"honnef.co/go/tools/stylecheck/st1006",
		"honnef.co/go/tools/stylecheck/st1008",
		"honnef.co/go/tools/stylecheck/st1011",
		"honnef.co/go/tools/stylecheck/st1012",
		"honnef.co/go/tools/stylecheck/st1013",
		"honnef.co/go/tools/stylecheck/st1015",
		"honnef.co/go/tools/stylecheck/st1016",
		"honnef.co/go/tools/stylecheck/st1017",
		"honnef.co/go/tools/stylecheck/st1018",
		"honnef.co/go/tools/stylecheck/st1019",
		"honnef.co/go/tools/stylecheck/st1020",
		"honnef.co/go/tools/stylecheck/st1021",
		"honnef.co/go/tools/stylecheck/st1022",
		"honnef.co/go/tools/stylecheck/st1023",
		"honnef.co/go/tools/unused",
		"html",
		"html/template",
		"internal/abi",
		"internal/asan",
		"internal/bisect",
		"internal/buildcfg",
		"internal/bytealg",
		"internal/byteorder",
		"internal/chacha8rand",
		"internal/coverage/rtcov",
		"internal/cpu",
		"internal/filepathlite",
		"internal/fmtsort",
		"internal/goarch",
		"internal/godebug",
		"internal/godebugs",
		"internal/goexperiment",
		"internal/goos",
		"internal/goroot",
		"internal/gover",
		"internal/goversion",
		"internal/itoa",
		"internal/lazyregexp",
		"internal/msan",
		"internal/nettrace",
		"internal/oserror",
		"internal/platform",
		"internal/poll",
		"internal/profilerecord",
		"internal/race",
		"internal/reflectlite",
		"internal/runtime/atomic",
		"internal/runtime/exithook",
		"internal/runtime/maps",
		"internal/runtime/math",
		"internal/runtime/sys",
		"internal/runtime/syscall",
		"internal/saferio",
		"internal/singleflight",
		"internal/stringslite",
		"internal/sync",
		"internal/syscall/execenv",
		"internal/syscall/unix",
		"internal/syslist",
		"internal/testlog",
		"internal/types/errors",
		"internal/unsafeheader",
		"internal/zstd",
		"io",
		"io/fs",
		"io/ioutil",
		"iter",
		"log",
		"log/internal",
		"maps",
		"math",
		"math/big",
		"math/bits",
		"math/rand",
		"math/rand/v2",
		"mime",
		"mime/multipart",
		"mime/quotedprintable",
		"net",
		"net/http",
		"net/http/httptrace",
		"net/http/internal",
		"net/http/internal/ascii",
		"net/netip",
		"net/textproto",
		"net/url",
		"os",
		"os/exec",
		"os/signal",
		"path",
		"path/filepath",
		"reflect",
		"regexp",
		"regexp/syntax",
		"runtime",
		"runtime/debug",
		"runtime/pprof",
		"runtime/trace",
		"slices",
		"sort",
		"strconv",
		"strings",
		"sync",
		"sync/atomic",
		"syscall",
		"text/tabwriter",
		"text/template",
		"text/template/parse",
		"time",
		"unicode",
		"unicode/utf16",
		"unicode/utf8",
		"unique",
		"unsafe",
		"vendor/golang.org/x/crypto/chacha20",
		"vendor/golang.org/x/crypto/chacha20poly1305",
		"vendor/golang.org/x/crypto/cryptobyte",
		"vendor/golang.org/x/crypto/cryptobyte/asn1",
		"vendor/golang.org/x/crypto/internal/alias",
		"vendor/golang.org/x/crypto/internal/poly1305",
		"vendor/golang.org/x/net/dns/dnsmessage",
		"vendor/golang.org/x/net/http/httpguts",
		"vendor/golang.org/x/net/http/httpproxy",
		"vendor/golang.org/x/net/http2/hpack",
		"vendor/golang.org/x/net/idna",
		"vendor/golang.org/x/sys/cpu",
		"vendor/golang.org/x/text/secure/bidirule",
		"vendor/golang.org/x/text/transform",
		"vendor/golang.org/x/text/unicode/bidi",
		"vendor/golang.org/x/text/unicode/norm",
		"weak"
	]
}
go list -m -json honnef.co/go/tools
{
	"Path": "honnef.co/go/tools",
	"Version": "v0.5.1",
	"Time": "2024-08-14T20:27:15Z",
	"Indirect": true,
	"Dir": "/home/user/.data/go/pkg/mod/honnef.co/go/tools@v0.5.1",
	"GoMod": "/home/user/.data/go/pkg/mod/cache/download/honnef.co/go/tools/@v/v0.5.1.mod",
	"GoVersion": "1.22.1",
	"Sum": "h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=",
	"GoModSum": "h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs="
}

A tool dependency shows no relation to the main module

$ go mod why honnef.co/go/tools/cmd/staticcheck
# honnef.co/go/tools/cmd/staticcheck
honnef.co/go/tools/cmd/staticcheck

$ go mod why -m honnef.co/go/tools
# honnef.co/go/tools
honnef.co/go/tools/cmd/staticcheck

Compared to a direct dependency

$ go mod why golang.org/x/sync/errgroup
# golang.org/x/sync/errgroup
go.seankhliao.com/mono/yrun
golang.org/x/sync/errgroup

$ go mod why -m golang.org/x/sync
# golang.org/x/sync
go.seankhliao.com/mono/yrun
golang.org/x/sync/errgroup

But it is listed as a dependency edge in the module graph:

$ go mod graph | grep honnef.co/go/tools
go.seankhliao.com/mono honnef.co/go/tools@v0.5.1
# ... omitted ...

What did you see happen?

I think tool dependencies are not consistently represented in go mod graph, go mod why, go list output.
And there's no way to identify whether a package / module is a tool dependency (except maybe checking against go list tool).

What did you expect to see?

Not sure if it should be consistently directly linked or detached from the main module.
And some attribute in the package to identify it being pulled in as a tool.

@seankhliao seankhliao added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. GoCommand cmd/go labels Nov 26, 2024
@seankhliao
Copy link
Member Author

cc @matloob @samthanawalla

@seankhliao
Copy link
Member Author

I noticed something a bit unintuitive while looking at #27719:
with a go.mod but without any .go files in the main module:

  • go list all is empty,
  • adding tool directives results in go list all outputing packages for the tools and their dependencies, but ignores any tools in the main module.

@matloob
Copy link
Contributor

matloob commented Dec 5, 2024

@seankhliao Could you give an example of the tools in the main module being ignored?

@seankhliao
Copy link
Member Author

With just this file:

module go.seankhliao.com/testrepo0962

go 1.24

tool (
    go.seankhliao.com/testrepo0962/cmd/mytool
)

results in

$ go list all
go: warning: "all" matched no packages

Which seems inconsistent with how it handles other tools (I would have expected either consistently no packages matched, or an error saying it has insufficient information about cmd/mytool

with an external tool
module go.seankhliao.com/testrepo0962

go 1.24

tool (
	go.seankhliao.com/testrepo0962/cmd/mytool
	golang.org/x/tools/cmd/stringer
)

require (
	golang.org/x/mod v0.22.0 // indirect
	golang.org/x/sync v0.10.0 // indirect
	golang.org/x/tools v0.28.0 // indirect
)
$ go list all
bufio
bytes
cmp
container/heap
context
crypto
crypto/internal/fips140
crypto/internal/fips140/alias
crypto/internal/fips140/sha256
crypto/internal/fips140/sha3
crypto/internal/fips140/sha512
crypto/internal/fips140/subtle
crypto/internal/fips140deps/byteorder
crypto/internal/fips140deps/cpu
crypto/internal/fips140deps/godebug
crypto/internal/fips140only
crypto/internal/impl
crypto/md5
encoding
encoding/base64
encoding/binary
encoding/json
errors
flag
fmt
go/ast
go/build
go/build/constraint
go/constant
go/doc
go/doc/comment
go/format
go/parser
go/printer
go/scanner
go/token
go/types
go/version
golang.org/x/mod/semver
golang.org/x/sync/errgroup
golang.org/x/tools/cmd/stringer
golang.org/x/tools/go/gcexportdata
golang.org/x/tools/go/packages
golang.org/x/tools/go/types/objectpath
golang.org/x/tools/go/types/typeutil
golang.org/x/tools/internal/aliases
golang.org/x/tools/internal/event
golang.org/x/tools/internal/event/core
golang.org/x/tools/internal/event/keys
golang.org/x/tools/internal/event/label
golang.org/x/tools/internal/gcimporter
golang.org/x/tools/internal/gocommand
golang.org/x/tools/internal/packagesinternal
golang.org/x/tools/internal/pkgbits
golang.org/x/tools/internal/stdlib
golang.org/x/tools/internal/typeparams
golang.org/x/tools/internal/typesinternal
golang.org/x/tools/internal/versions
hash
internal/abi
internal/asan
internal/bisect
internal/buildcfg
internal/bytealg
internal/byteorder
internal/chacha8rand
internal/coverage/rtcov
internal/cpu
internal/filepathlite
internal/fmtsort
internal/goarch
internal/godebug
internal/godebugs
internal/goexperiment
internal/goos
internal/goroot
internal/gover
internal/goversion
internal/itoa
internal/lazyregexp
internal/msan
internal/oserror
internal/platform
internal/poll
internal/profilerecord
internal/race
internal/reflectlite
internal/runtime/atomic
internal/runtime/exithook
internal/runtime/maps
internal/runtime/math
internal/runtime/sys
internal/runtime/syscall
internal/stringslite
internal/sync
internal/syscall/execenv
internal/syscall/unix
internal/syslist
internal/testlog
internal/types/errors
internal/unsafeheader
io
io/fs
iter
log
log/internal
math
math/big
math/bits
math/rand
os
os/exec
path
path/filepath
reflect
regexp
regexp/syntax
runtime
slices
sort
strconv
strings
sync
sync/atomic
syscall
text/tabwriter
time
unicode
unicode/utf16
unicode/utf8
unsafe

@matloob
Copy link
Contributor

matloob commented Dec 5, 2024

cc @ConradIrwin

Since the tool directive implies an import of the tool package, I think we should be producing an error similar to an ImportMissingError.

With these files:

-- foo.go --
package foo

import "example.com/foo/bar/baz"
-- go.mod --
module example.com/foo

go 1.24

go list all would produce the error:

foo.go:3:8: no required module provides package golang.org/x/tools/go/packages; to add it:
	go get golang.org/x/tools/go/packages

So in the example above we'd want the following:

go.mod:6:4: no required module provides package go.seankhliao.com/testrepo0962/cmd/mytool; to add it:
	go get go.seankhliao.com/testrepo0962/cmd/mytool

edit: it might be a bit annoying to add the go.mod:6:4 part so maybe we just print the importmissingerror

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/634155 mentions this issue: cmd/go: report tool errors in go list all

@ConradIrwin
Copy link
Contributor

I've sent a CL for the missing error in go list all.

I think the behavior of go mod graph is correct.

I'm not sure what to do about go mod why.

I think we could either (in order of preference):

  1. Document the current behavior. go mod why shows the import graph, and tool packages are not imported by other packages and so show up as roots in the import graph.
  2. Add a new line to the section:
    $ go mod why honnef.co/go/tools/cmd/staticcheck
    # honnef.co/go/tools/cmd/staticcheck
    tool
    honnef.co/go/tools/cmd/staticcheck
    
  3. Add a hint to the heading:
     # honnef.co/go/tools/cmd/staticcheck (tool)
     honnef.co/go/tools/cmd/staticcheck
    

I think (3) is problematic because it makes parsing the output needlessly harder; I think (2) is a more reasonable compromise: it's clear to human readers, and parsers only need to be ok getting a meta-pattern instead of the package path. That said, the current behavior seems reasonable to me, so maybe (1) is the best option?

@matloob
Copy link
Contributor

matloob commented Dec 6, 2024

Reopening this until we have a decision on go mod why.

If we weren't worried about breaking tools that invoked go mod why, I'd suggest something like this:

$ go mod why honnef.co/go/tools/cmd/staticcheck
# honnef.co/go/tools/cmd/staticcheck
honnef.co/go/tools/cmd/staticcheck # tool of go.seankhliao.com/testrepo0962

where we indicate the module that "imported" the tool on the line for the tool in the import stack.

One thing we could consider for go mod graph is that it returns a one line parenthesized statement if the module isn't referenced from the main module. from go help mod why:

For example:

	$ go mod why golang.org/x/text/language golang.org/x/text/encoding
	# golang.org/x/text/language
	rsc.io/quote
	rsc.io/sampler
	golang.org/x/text/language

	# golang.org/x/text/encoding
	(main module does not need package golang.org/x/text/encoding)
	$

Perhaps we could do something similar to option 2, but instead of specifying tool we'd say that the package is a tool of <module tool directive is in>

$ go mod why honnef.co/go/tools/cmd/staticcheck
# honnef.co/go/tools/cmd/staticcheck
(honnef.co/go/tools/cmd/staticcheck is a tool of go.seankhliao.com/testrepo0962)
honnef.co/go/tools/cmd/staticcheck

Tools invoking go mod why may still not like this because currently the parenthesized statement only appears by itself, so we would be changing the output format a bit.

But I think if we do go with an option other than option 1, we should specify the module that requires the tool to clarify where the tool comes from in the case of workspaces.

@matloob matloob reopened this Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GoCommand cmd/go NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

5 participants