You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The exhaustruct linter has false positives ever since golangci-lint upgraded to Go 1.23 in the v1.65.0 release. That release replaced the go 1.22 directive in go.mod with go 1.23, causing the linter's behaviour to change.
I used git bisect to identify PR #5224 as the one that introduced the change. Further investigation confirmed that changing the go 1.22 directive to go 1.23 is what causes the change in behaviour.
The issue is that in golangci-lint v1.63.x, the exhaustruct linter reported missing fields in structs where the type was a type alias. In v1.64.x, the linter no longer reports missing fields in structs where the type is an alias. See below for an example of code that reports an error with v1.64 but not with v1.65.
The exhaustruct linter was not upgraded in the v1.64 release of golangci-lint.
Running the linter directly does not suffer from the same issue, because that project's go.mod contains the go 1.21 directive. The issue only occurs when the analyzer is imported as a library into a project with go 1.23 or go 1.24 in its go.mod.
I want to be clear: I don't think the buggy code is in golangci-lint. But the bug only appears in golangci-lint. I've opened an issue on the linter's repository to fix this: GaijinEntertainment/go-exhaustruct#129. I am opening this issue here to track the problem, in case other analyzers are also affected.
Version of golangci-lint
Version with incorrect linter behaviour:
$ golangci-lint --versiongolangci-lint has version 1.64.4 built with go1.24.0 from 04aec4f7 on 2025-02-12T21:58:21Z
Version with correct linter behaviour:
$ golangci-lint --versiongolangci-lint has version 1.63.4 built with go1.23.4 from c1149695 on 2025-01-03T19:49:42Z
Configuration
$ golangci-lint run --enable-only=exhaustruct
Go environment
$ go version && go envgo version go1.24.0 darwin/arm64AR='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/arthur/Library/Caches/go-build'GOCACHEPROG=''GODEBUG=''GOENV='/Users/arthur/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/80/tqlcnm9d5_jbbmvnx9zst7rr0000gn/T/go-build2107305147=/tmp/go-build -gno-record-gcc-switches -fno-common'GOHOSTARCH='arm64'GOHOSTOS='darwin'GOINSECURE=''GOMOD='/Users/arthur/workspace/pigment/monorepo/go.mod'GOMODCACHE='/Users/arthur/go/pkg/mod'GONOPROXY=''GONOSUMDB=''GOOS='darwin'GOPATH='/Users/arthur/go'GOPRIVATE=''GOPROXY='https://proxy.golang.org,direct'GOROOT='/opt/homebrew/Cellar/go/1.24.0/libexec'GOSUMDB='sum.golang.org'GOTELEMETRY='on'GOTELEMETRYDIR='/Users/arthur/Library/Application Support/go/telemetry'GOTMPDIR=''GOTOOLCHAIN='auto'GOTOOLDIR='/opt/homebrew/Cellar/go/1.24.0/libexec/pkg/tool/darwin_arm64'GOVCS=''GOVERSION='go1.24.0'GOWORK=''PKG_CONFIG='pkg-config'
Verbose output of running
With golangci-lint v1.64.4:
$ golangci-lint cache clean
$ golangci-lint run -vINFO golangci-lint has version 1.64.4 built with go1.24.0 from 04aec4f7 on 2025-02-12T21:58:21ZINFO [config_reader] Config search paths: [./ /Users/arthur/workspace/pigment/tmp /Users/arthur/workspace/pigment /Users/arthur/workspace /Users/arthur /Users /]INFO [goenv] Read go env for 9.668583ms: map[string]string{"GOCACHE":"/Users/arthur/Library/Caches/go-build", "GOROOT":"/opt/homebrew/Cellar/go/1.24.0/libexec"}INFO [lintersdb] Active 1 linters: [exhaustruct]INFO [loader] Go packages loading at mode 8767 (compiled_files|deps|imports|name|exports_file|files|types_sizes) took 34.408083msINFO [runner/filename_unadjuster] Pre-built 0 adjustments in 420.959µsINFO [linters_context/goanalysis] analyzers took 29.583µs with top 10 stages: inspect: 18.708µs, typecheck: 7.5µs, exhaustruct: 3.375µsINFO [runner] processing took 1.167µs with stages: max_same_issues: 292ns, exclusion_paths: 166ns, exclusion_rules: 125ns, max_from_linter: 83ns, diff: 42ns, path_absoluter: 42ns, source_code: 42ns, fixer: 42ns, path_shortener: 42ns, severity-rules: 42ns, path_relativity: 42ns, invalid_issue: 42ns, sort_results: 42ns, generated_file_filter: 41ns, skip_dirs: 41ns, path_prettifier: 41ns, uniq_by_line: 0s, nolint_filter: 0s, identifier_marker: 0s, filename_unadjuster: 0s, cgo: 0s, skip_files: 0s, max_per_file_from_linter: 0sINFO [runner] linters took 1.3655ms with stages: goanalysis_metalinter: 1.330625msINFO File cache stats: 0 entries of total size 0BINFO Memory: 2 samples, avg is 32.6MB, max is 34.6MBINFO Execution took 46.725458ms
With golangci-lint v1.63.4:
$ golangci-lint cache clean
$ golangci-lint run -v --enable-only=exhaustructINFO golangci-lint has version 1.63.4 built with go1.23.4 from c1149695 on 2025-01-03T19:49:42ZINFO [config_reader] Config search paths: [./ /Users/arthur/workspace/pigment/tmp /Users/arthur/workspace/pigment /Users/arthur/workspace /Users/arthur /Users /]INFO [lintersdb] Active 1 linters: [exhaustruct]INFO [loader] Go packages loading at mode 8767 (compiled_files|deps|imports|name|exports_file|files|types_sizes) took 32.116125msINFO [runner/filename_unadjuster] Pre-built 0 adjustments in 187.875µsINFO [linters_context/goanalysis] analyzers took 64.043µs with top 10 stages: inspect: 35.834µs, exhaustruct: 20.792µs, typecheck: 7.417µsINFO [runner] Processors filtering stat (in/out): path_prettifier: 1/1, nolint: 1/1, diff: 1/1, fixer: 1/1, sort_results: 1/1, cgo: 1/1, skip_dirs: 1/1, max_per_file_from_linter: 1/1, max_same_issues: 1/1, invalid_issue: 1/1, source_code: 1/1, path_shortener: 1/1, severity-rules: 1/1, path_prefixer: 1/1, autogenerated_exclude: 1/1, skip_files: 1/1, identifier_marker: 1/1, exclude: 1/1, exclude-rules: 1/1, uniq_by_line: 1/1, max_from_linter: 1/1, filename_unadjuster: 1/1INFO [runner] processing took 348.159µs with stages: nolint: 95.792µs, source_code: 81.875µs, autogenerated_exclude: 70.999µs, identifier_marker: 56.208µs, path_prettifier: 21.917µs, exclude-rules: 11.875µs, skip_dirs: 4.083µs, uniq_by_line: 957ns, max_same_issues: 874ns, invalid_issue: 791ns, path_shortener: 625ns, cgo: 583ns, max_from_linter: 416ns, max_per_file_from_linter: 250ns, fixer: 208ns, filename_unadjuster: 207ns, exclude: 167ns, skip_files: 166ns, sort_results: 42ns, diff: 42ns, path_prefixer: 41ns, severity-rules: 41nsINFO [runner] linters took 21.386792ms with stages: goanalysis_metalinter: 20.962125msfoo.go:11:6: foo.Foo is missing field B (exhaustruct) _ = FooAlias{ ^INFO File cache stats: 1 entries of total size 113BINFO Memory: 2 samples, avg is 26.6MB, max is 26.6MBINFO Execution took 66.264875ms
A minimal reproducible example or link to a public repository
Welcome
typecheck
section of the FAQ.Description of the problem
The
exhaustruct
linter has false positives ever sincegolangci-lint
upgraded to Go 1.23 in the v1.65.0 release. That release replaced thego 1.22
directive ingo.mod
withgo 1.23
, causing the linter's behaviour to change.I used
git bisect
to identify PR #5224 as the one that introduced the change. Further investigation confirmed that changing thego 1.22
directive togo 1.23
is what causes the change in behaviour.The issue is that in
golangci-lint
v1.63.x, theexhaustruct
linter reported missing fields in structs where the type was a type alias. In v1.64.x, the linter no longer reports missing fields in structs where the type is an alias. See below for an example of code that reports an error with v1.64 but not with v1.65.The
exhaustruct
linter was not upgraded in the v1.64 release ofgolangci-lint
.Running the linter directly does not suffer from the same issue, because that project's
go.mod
contains thego 1.21
directive. The issue only occurs when the analyzer is imported as a library into a project withgo 1.23
orgo 1.24
in itsgo.mod
.I want to be clear: I don't think the buggy code is in
golangci-lint
. But the bug only appears ingolangci-lint
. I've opened an issue on the linter's repository to fix this: GaijinEntertainment/go-exhaustruct#129. I am opening this issue here to track the problem, in case other analyzers are also affected.Version of golangci-lint
Version with incorrect linter behaviour:
Version with correct linter behaviour:
Configuration
$ golangci-lint run --enable-only=exhaustruct
Go environment
Verbose output of running
With
golangci-lint
v1.64.4:With
golangci-lint
v1.63.4:A minimal reproducible example or link to a public repository
Validation
Supporter
The text was updated successfully, but these errors were encountered: