Skip to content

go: "go" directive in modules does not prevent using new stdlib code #73603

Closed as not planned
@Groxx

Description

@Groxx

Go version

go version go1.24.2 darwin/arm64

Output of go env in your module/workspace:

❯ go env
AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/stevenl/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/stevenl/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/zp/sqm92pj94sq7whfh1rl3yjd00000gn/T/go-build3995360884=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/stevenl/go/src/go.uber.org/cadence/go.mod'
GOMODCACHE='/Users/stevenl/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/stevenl/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.24.2/libexec'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/stevenl/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.24.2/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.24.2'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

go build ./... in a project using 1.24-specific stdlib packages/methods, but a 1.21-specific go.mod file.

What did you see happen?

Build (and run) succeeded.

Demo in the playground: https://go.dev/play/p/qqJqFz5G8et

What did you expect to see?

Given the go 1.21 version in go.mod, I expected the build to fail as if it was built using go 1.21, e.g. GOTOOLCHAIN=go1.21.1 go build ./... which produces errors like

prog.go:5:2: package weak is not in std (/usr/local/go-faketime/src/weak)

But this does not happen.

This too-old-version build failure is currently reproducible in the playground with the previous go version, e.g. https://go.dev/play/p/qqJqFz5G8et?v=goprev which uses go 1.23, but I'm not sure how to target specific versions to make a stable link.

The go module reference seems to imply the go version should protect against new Go things:

The go directive affects use of new language features:

  • For packages within the module, the compiler rejects use of language features introduced after the version specified by the go directive. For example, if a module has the directive go 1.12, its packages may not use numeric literals like 1_000_000, which were introduced in Go 1.13.

But perhaps this is only for "language features" like generics, not "language features" like the standard library? TBH I'm not sure that distinction makes much sense, the two are inseparable for essentially all users.

go vet also does not complain about this, nor does go mod tidy try to upgrade the target version. Currently this seems to mean that we need to set up a manual test matrix to build with multiple Go versions, just to check something that can be statically determined.
This seems... subpar?

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions