golangci / golangci-lint

Fast linters runner for Go
https://golangci-lint.run
GNU General Public License v3.0
15.27k stars 1.36k forks source link

goanalysis_metalinter: failed to load package main: could not load export data #4630

Closed nchepanov-plaid closed 5 months ago

nchepanov-plaid commented 5 months ago

Welcome

Description of the problem

In my go repository I need to add delve to go.mod.

Since delve is a tool, the recommended way of doing it is including a noop import (see reproducer). Everything works as expected except that the linter now breaks in very strange way that I wasn't able to work around.

Version of golangci-lint

```console $ golangci-lint --version golangci-lint has version v1.55.2 built with go1.20.6 from (unknown, mod sum: "h1:yllEIsSJ7MtlDBwDJ9IMBkyEUz2fYE0b5B8IUgO1oP8=") on (unknown) ```

Configuration

```console --no-config ```

Go environment

```console $ go version && go env go version go1.20.6 darwin/arm64 GO111MODULE="on" GOARCH="arm64" GOBIN="" GOCACHE="/Users/nchepanov/Library/Caches/go-build" GOENV="/Users/nchepanov/Library/Application Support/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="arm64" GOHOSTOS="darwin" GOINSECURE="" GOMODCACHE="/Users/nchepanov/go/pkg/mod" GONOPROXY="redacted" GONOSUMDB="redacted" GOOS="darwin" GOPATH="/Users/nchepanov/go" GOPRIVATE="redacted" GOPROXY="https://proxy.golang.org" GOROOT="/opt/homebrew/opt/go/libexec" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/opt/homebrew/opt/go/libexec/pkg/tool/darwin_arm64" GOVCS="" GOVERSION="go1.20.6" GCCGO="gccgo" AR="ar" CC="cc" CXX="c++" CGO_ENABLED="1" GOMOD="redacted/go.git/go.mod" GOWORK="" CGO_CFLAGS="-O2 -g" CGO_CPPFLAGS="" CGO_CXXFLAGS="-O2 -g" CGO_FFLAGS="-O2 -g" CGO_LDFLAGS="-O2 -g" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/sm/p46qjwpj0bl89qz0qnsy15xc0000gp/T/go-build3031631975=/tmp/go-build -gno-record-gcc-switches -fno-common" ```

Verbose output of running

```console $ golangci-lint cache clean $ golangci-lint run -v --no-config reproducer INFO [lintersdb] Active 6 linters: [errcheck gosimple govet ineffassign staticcheck unused] INFO [loader] Go packages loading at mode 575 (imports|types_sizes|compiled_files|deps|exports_file|files|name) took 202.7705ms INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 89.875µs INFO [linters_context/goanalysis] analyzers took 1.808611ms with top 10 stages: ctrlflow: 287.245µs, buildir: 204.594µs, inspect: 88.917µs, nilness: 74.253µs, fact_deprecated: 71.404µs, fact_purity: 55.383µs, printf: 42.742µs, directives: 41.166µs, SA5012: 39.409µs, typedness: 37.873µs WARN [runner] Can't run linter goanalysis_metalinter: buildir: failed to load package main: could not load export data: no export data for "github.com/go-delve/delve/cmd/dlv" INFO [runner] processing took 2.086µs with stages: max_same_issues: 459ns, skip_dirs: 416ns, nolint: 250ns, cgo: 125ns, filename_unadjuster: 125ns, path_prettifier: 84ns, max_from_linter: 83ns, uniq_by_line: 83ns, sort_results: 42ns, path_shortener: 42ns, exclude-rules: 42ns, max_per_file_from_linter: 42ns, autogenerated_exclude: 42ns, fixer: 42ns, diff: 42ns, source_code: 42ns, severity-rules: 42ns, path_prefixer: 42ns, skip_files: 41ns, identifier_marker: 0s, exclude: 0s INFO [runner] linters took 207.444042ms with stages: goanalysis_metalinter: 207.414666ms ERRO Running error: 1 error occurred: * can't run linter goanalysis_metalinter: buildir: failed to load package main: could not load export data: no export data for "github.com/go-delve/delve/cmd/dlv" INFO Memory: 6 samples, avg is 42.2MB, max is 69.1MB INFO Execution took 421.803541ms ```

A minimal reproducible example or link to a public repository

`reproducer/required.go` ```go //nolint:all package packages import _ "github.com/go-delve/delve/cmd/dlv" ```

Validation

boring-cyborg[bot] commented 5 months ago

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

ldez commented 5 months ago

Hello,

buildir detects compilation errors.

package main

import _ "github.com/go-delve/delve/cmd/dlv"
$ go build              
main.go:4:8: import "github.com/go-delve/delve/cmd/dlv" is a program, not an importable package

This error is expected because github.com/go-delve/delve/cmd/dlv is a main package so it cannot be imported.

nolint directives cannot be used to ignore compilation errors.

You are misusing the tools pattern: this pattern required a dedicated file (ex: tools.go) and a dedicated build tag (//go:build tools).

I recommend not using this pattern because it has side effects (ex: dependencies of a tool can change the dependencies of another tool).

nchepanov-plaid commented 5 months ago

Ah, this makes sense! Thank you!

Unfortunately even with correct usage of the pattern I'm still seeing the linter error, and I understand that the linter error just points at the build error: not an importable package.

What do you suggest to use instead of the tools pattern? In my case I use Bazel to read go.mod and go.mod is automatically populated by go mod tidy. Are you aware of other ways to include an installable go package into a repository?

ldez commented 5 months ago

Unfortunately even with correct usage of the pattern I'm still seeing the linter error,

It works if you don't use the build tags with golangci-lint:

tools.go ```go //go:build tools package main import _ "github.com/go-delve/delve/cmd/dlv" ```
main.go ```go package main import "fmt" func main() { fmt.Println("hello") } ```
$ golangci-lint run                                                             
$ 

If I use the build tag to run golangci-lint:

$ golangci-lint run --build-tags tools                                         
tools.go:5:8: import "github.com/go-delve/delve/cmd/dlv" is a program, not an importable package (typecheck)
import _ "github.com/go-delve/delve/cmd/dlv"
       ^
$

If I remove the directive //go:build tools:

$ golangci-lint run
tools.go:3:8: import "github.com/go-delve/delve/cmd/dlv" is a program, not an importable package (typecheck)
import _ "github.com/go-delve/delve/cmd/dlv"
       ^
$

What do you suggest to use instead of the tools pattern?

It's a personal preference, but I just install tools locally with go install. You can use a script, or a make target, or something else to automate that if you want.