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

False negatives with exhaustruct caused by upgrade to Go 1.23 #5416

Closed
6 of 7 tasks
busser opened this issue Feb 14, 2025 · 2 comments
Closed
6 of 7 tasks

False negatives with exhaustruct caused by upgrade to Go 1.23 #5416

busser opened this issue Feb 14, 2025 · 2 comments
Labels
bug Something isn't working dependencies Relates to an upstream dependency

Comments

@busser
Copy link

busser commented Feb 14, 2025

Welcome

  • Yes, I'm using a binary release within 2 latest releases. Only such installations are supported.
  • Yes, I've searched similar issues on GitHub and didn't find any.
  • Yes, I've read the typecheck section of the FAQ.
  • Yes, I've tried with the standalone linter if available (e.g., gocritic, go vet, etc.).
  • I agree to follow this project's Code of Conduct

Description of the problem

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 --version
golangci-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 --version
golangci-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 env
go version go1.24.0 darwin/arm64
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/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 -v
INFO golangci-lint has version 1.64.4 built with go1.24.0 from 04aec4f7 on 2025-02-12T21:58:21Z
INFO [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.408083ms
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 420.959µs
INFO [linters_context/goanalysis] analyzers took 29.583µs with top 10 stages: inspect: 18.708µs, typecheck: 7.5µs, exhaustruct: 3.375µs
INFO [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: 0s
INFO [runner] linters took 1.3655ms with stages: goanalysis_metalinter: 1.330625ms
INFO File cache stats: 0 entries of total size 0B
INFO Memory: 2 samples, avg is 32.6MB, max is 34.6MB
INFO Execution took 46.725458ms

With golangci-lint v1.63.4:

$ golangci-lint cache clean
$ golangci-lint run -v --enable-only=exhaustruct
INFO golangci-lint has version 1.63.4 built with go1.23.4 from c1149695 on 2025-01-03T19:49:42Z
INFO [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.116125ms
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 187.875µs
INFO [linters_context/goanalysis] analyzers took 64.043µs with top 10 stages: inspect: 35.834µs, exhaustruct: 20.792µs, typecheck: 7.417µs
INFO [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/1
INFO [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: 41ns
INFO [runner] linters took 21.386792ms with stages: goanalysis_metalinter: 20.962125ms
foo.go:11:6: foo.Foo is missing field B (exhaustruct)
        _ = FooAlias{
            ^
INFO File cache stats: 1 entries of total size 113B
INFO Memory: 2 samples, avg is 26.6MB, max is 26.6MB
INFO Execution took 66.264875ms

A minimal reproducible example or link to a public repository

package foo

type Foo struct {
        A int
        B int
}

type FooAlias = Foo

func MyFunc() {
        _ = FooAlias{
                A: 1,
        }
}

Validation

  • Yes, I've included all information above (version, config, etc.).

Supporter

@busser busser added the bug Something isn't working label Feb 14, 2025
Copy link

boring-cyborg bot commented Feb 14, 2025

Hey, thank you for opening your first Issue ! 🙂 If you would like to contribute we have a guide for contributors.

@ldez ldez added the dependencies Relates to an upstream dependency label Feb 14, 2025
@ldez
Copy link
Member

ldez commented Feb 14, 2025

The problem will be fixed upstream: GaijinEntertainment/go-exhaustruct#130

@ldez ldez closed this as completed Feb 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working dependencies Relates to an upstream dependency
Projects
None yet
Development

No branches or pull requests

2 participants