Skip to content

Build faillint from the main module instead of go install - #7816

Merged
friedrichg merged 1 commit into
masterfrom
faillint-tool-directive
Aug 27, 2026
Merged

Build faillint from the main module instead of go install#7816
friedrichg merged 1 commit into
masterfrom
faillint-tool-directive

Conversation

@friedrichg

@friedrichg friedrichg commented Aug 27, 2026

Copy link
Copy Markdown
Member

What this PR does:

Alternative to #7815, not a supplement. Both fix the same breakage and only one should land. SungJin1212 diagnosed the problem there and the diagnosis is correct; this PR disagrees only about the mechanism. #7815 force-upgrades golang.org/x/tools inside a throwaway module in the Dockerfile; this declares faillint as a tool dependency so the version comes from our own module graph.

The problem: go install github.com/fatih/faillint@v1.15.0 resolves faillint's own go.mod, so it builds against golang.org/x/tools v0.30.0, whose decoder stops at pkgbits V2. Go 1.27 writes V4, so faillint fails with internal error: package "net/http" without types was imported from .... Go 1.24 through 1.26 all wrote V2, which is why the stale pin cost nothing for three releases. faillint has had no upstream commit since 2025-03, so its pin will never advance on its own and every future pkgbits increment breaks it again.

Declaring faillint as a tool dependency lets MVS pick x/tools from the main module, which already requires v0.47.0 (declares V4, and carries the corrected unified reader from CL 765504). The skew becomes structurally impossible rather than a version number someone must remember to bump in a Dockerfile whenever the Go base image moves. This is the same mechanism the Go project used for its own vendored x/tools in golang/go#49159.

x/tools is deliberately left at v0.47.0. Forcing v0.49.0 also drags x/net, x/crypto, x/text and x/mod forward, and x/net is a direct dependency that ships in the binary; lint tooling should not move it.

Cost: 364 KB of vendored source (13 x/tools packages, faillint's analyzer, and dmitri.shuralyov.com/go/generated). build-image/Dockerfile loses a step, and make lint calls go tool faillint.

Verified on Go 1.27.0: all 8 faillint checks pass; a control run (-paths context) still reports violations and exits 3, so the checks are not passing vacuously; go build -tags "netgo slicelabels" ./... is clean; go mod tidy and go mod vendor are idempotent, so make mod-check passes. Lint stays hermetic: go tool faillint was verified with GOPROXY=off against vendor/, so the build image still needs no module cache.

Note Makefile has a second instance of this bug class: make modernize runs golang.org/x/tools/gopls/...@v0.22.0, which is safe on Go 1.27 only because that pin happens to postdate the V4 decode fixes. Left alone here.

Which issue(s) this PR fixes:
N/A

Checklist

  • Tests updated - n/a, build tooling. The faillint suite is itself the test, and the lint CI job exercises it.
  • Documentation added - n/a
  • CHANGELOG.md updated - n/a, build-image and lint tooling changes carry no entry, matching Upgrade golang to 1.27.0 and golangci-lint to 2.13.1 #7807
  • docs/configuration/v1-guarantees.md updated if this PR introduces experimental flags - n/a, no new flags

AI usage disclosure

Per §3 of GENAI_POLICY.md: the investigation behind this change and the text of this description were substantially AI-assisted (Claude Code). Per §1, I verified the claims myself: I confirmed the vendored x/tools v0.47.0 declares V4 and has the corrected reader, reproduced the old failure on Go 1.27 in golang:1.27.0-trixie, and ran the faillint suite plus the control case locally on Go 1.27.0.

`go install pkg@version` resolves the target's own go.mod, so
`go install github.com/fatih/faillint@v1.15.0` builds faillint against
golang.org/x/tools v0.30.0, the version faillint pins. That decoder tops out at
pkgbits V2.

Go 1.27 writes unified IR export data at pkgbits V4, so as soon as faillint
type-checks a package whose dependencies come from export data it fails with
`internal error: package "net/http" without types was imported from ...`. Go
1.24, 1.25 and 1.26 all wrote V2, which is why the stale pin cost nothing for
the last three releases. faillint has had no upstream commit since March 2025,
so its pin will never advance on its own and every future pkgbits increment
breaks it again.

Declare faillint as a tool dependency instead. Its x/tools version is then
chosen by the main module's graph rather than by faillint, and the repo already
requires golang.org/x/tools v0.47.0, which declares V4 and carries the
corrected unified reader. Minimum viable versions/skew handling is now a
property of MVS, not of a hardcoded number in a Dockerfile, so bumping the Go
toolchain cannot reintroduce the skew.

x/tools is deliberately left at v0.47.0. Forcing it to v0.49.0 also pulls
x/net, x/crypto, x/text and x/mod forward, and x/net is a direct dependency
that ships in the binary; the lint toolchain should not move it.

- build-image/Dockerfile no longer installs faillint.
- The lint target invokes `go tool faillint`.
- Adds 364 KB of vendored source: 13 x/tools packages, faillint's analyzer and
  dmitri.shuralyov.com/go/generated.

Lint stays hermetic: `go tool faillint` was verified to run with GOPROXY=off
against vendor/, so the build image needs no module cache. `go mod tidy` and
`go mod vendor` are idempotent, so `make mod-check` passes.

No CHANGELOG entry: build-image and lint tooling changes carry none, matching
the Go 1.27 bump in #7807.

Signed-off-by: Friedrich Gonzalez <1517449+friedrichg@users.noreply.github.com>
@friedrichg
friedrichg requested a review from a team as a code owner August 27, 2026 01:32
@friedrichg
friedrichg requested a review from alanprot August 27, 2026 01:32
@dosubot dosubot Bot added dependencies Pull requests that update a dependency file go Pull requests that update Go code type/chore Something that needs to be done; not a bug or a feature labels Aug 27, 2026
@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Aug 27, 2026
@friedrichg
friedrichg merged commit 7bc8b24 into master Aug 27, 2026
42 checks passed
@friedrichg
friedrichg deleted the faillint-tool-directive branch August 27, 2026 01:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file go Pull requests that update Go code lgtm This PR has been approved by a maintainer size/S type/chore Something that needs to be done; not a bug or a feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants