golangci / golangci-lint

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

Range-Over-Function is not supported #4627

Closed CuteReimu closed 5 months ago

CuteReimu commented 5 months ago

Welcome

Description of the problem

I tried to use the new experiment feature Range-Over-Function in Go1.22. I ensured GOEXPERIMENT is set correctly.

$ go env -w GOEXPERIMENT=rangefunc
$ go env GOEXPERIMENT              
rangefunc

I ensured the version of golangci-lint is latest.

go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

I can build the whole package successfully by go build. But golangci-lint can't recognize it.

Version of golangci-lint

$ golangci-lint --version
golangci-lint has version v1.57.2 built with go1.22.0 X:rangefunc from (unknown, modified: ?, mod sum: "h1:NNhxfZyL5He1WWDrIvl1a4n5bvWZBcgAqBwlJAAgLTw=") on (unknown)

Configuration

No configuration file.

Go environment

```console $ go version && go env set GO111MODULE=on set GOARCH=amd64 set GOBIN= set GOCACHE=***\***\***\AppData\Local\go-build set GOENV=***\***\***\AppData\Roaming\go\env set GOEXE=.exe set GOEXPERIMENT=rangefunc set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOINSECURE= set GOMODCACHE=***\GoPath\pkg\mod set GONOPROXY= set GONOSUMDB= set GOOS=windows set GOPATH=***\GoPath set GOPRIVATE= set GOPROXY=https://proxy.golang.org,direct set GOROOT=***/***/go1.22.0 set GOSUMDB=off set GOTMPDIR= set GOTOOLCHAIN=auto set GOTOOLDIR=***\***\go1.22.0\pkg\tool\windows_amd64 set GOVCS= set GOVERSION=go1.22.0 set GCCGO=gccgo set GOAMD64=v1 set AR=ar set CC=gcc set CXX=g++ set CGO_ENABLED=1 set GOMOD=***\***\***\go.mod set GOWORK= set CGO_CFLAGS=-O2 -g set CGO_CPPFLAGS= set CGO_CXXFLAGS=-O2 -g set CGO_FFLAGS=-O2 -g set CGO_LDFLAGS=-O2 -g set PKG_CONFIG=pkg-config set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=***\***\***\AppData\Local\Temp\go-build2315178312=/tmp/go-build -gno-record-gcc-switches ```

Verbose output of running

```console $ golangci-lint cache clean $ golangci-lint run -v level=info msg="[config_reader] Config search paths: [./ ***\\***\\*** ***\\*** ***\\ ***\\***\\***]" level=info msg="[lintersdb] Active 6 linters: [errcheck gosimple govet ineffassign staticcheck unused]" level=info msg="[loader] Go packages loading at mode 575 (deps|imports|compiled_files|exports_file|files|name|types_sizes) took 442.1639ms" level=info msg="[runner/filename_unadjuster] Pre-built 0 adjustments in 2.6545ms" level=error msg="[linters_context] typechecking error: ***\\***\\***\\***\\ranges_test.go:6:17: cannot range over Range(1, 5) (value of type func(func(int) bool))" level=info msg="[linters_context/goanalysis] analyzers took 4.0694235s with top 10 stages: buildir: 1.3975746s, ctrlflow: 458.7113ms, fact_deprecated: 449.2427ms, printf: 398.5335ms, fact_purity: 327.9202ms, nilness: 326.2877ms, typedness: 314.7187ms, SA5012: 312.8353ms, inspect: 40.0902ms, SA2003: 3.2473ms" level=info msg="[runner] processing took 0s with stages: exclude: 0s, exclude-rules: 0s, max_per_file_from_linter: 0s, path_shortener: 0s, invalid_issue: 0s, skip_files: 0s, skip_dirs: 0s, autogenerated_ex clude: 0s, diff: 0s, max_same_issues: 0s, filename_unadjuster: 0s, nolint: 0s, max_from_linter: 0s, fixer: 0s, cgo: 0s, path_prettifier: 0s, identifier_marker: 0s, uniq_by_line: 0s, source_code: 0s, severity-rules: 0s, path_prefixer: 0s, sort_results: 0s" level=info msg="[runner] linters took 1.062843s with stages: goanalysis_metalinter: 1.062843s" level=info msg="File cache stats: 0 entries of total size 0B" level=info msg="Memory: 17 samples, avg is 142.6MB, max is 277.4MB" level=info msg="Execution took 1.5376979s" ```

A minimal reproducible example or link to a public repository

func Range(start, end int) func(func(int) bool) {
    return func(f func(int) bool) {
        for i := start; i < end; i++ {
            if !f(i) {
                break
            }
        }
    }
}

func main() {
    for i := range Range(1, 5) {
        fmt.Println(i)
    }
}

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

By default, we don't support GOEXPERIMENT.

Even with the right way to compile and run golangci-lint with rangefunc, it's not supported by linters.

```console $ GOEXPERIMENT=rangefunc ./golangci-lint run ERRO [linters_context/goanalysis] buildir: panic during analysis: Cannot range over: func(func(int) bool), goroutine 856 [running]: runtime/debug.Stack() /usr/lib/go/src/runtime/debug/stack.go:24 +0x5e github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func1() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:104 +0x5a panic({0x17486a0?, 0xc00c8af970?}) /usr/lib/go/src/runtime/panic.go:770 +0x132 honnef.co/go/tools/go/ir.(*builder).rangeStmt(0xc0025bd900, 0xc0023ae640, 0xc003952300, 0x0, {0x1c43458, 0xc003952300}) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/go/ir/builder.go:2225 +0x894 honnef.co/go/tools/go/ir.(*builder).stmt(0xc0025bd900, 0xc0023ae640, {0x1c47970?, 0xc003952300?}) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/go/ir/builder.go:2438 +0x20a honnef.co/go/tools/go/ir.(*builder).stmtList(...) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/go/ir/builder.go:859 honnef.co/go/tools/go/ir.(*builder).stmt(0xc0025bd900, 0xc0023ae640, {0x1c47880?, 0xc00109f2c0?}) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/go/ir/builder.go:2396 +0x1415 honnef.co/go/tools/go/ir.(*builder).buildFunction(0xc0025bd900, 0xc0023ae640) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/go/ir/builder.go:2508 +0x417 honnef.co/go/tools/go/ir.(*builder).buildFuncDecl(0xc0025bd900, 0xc000983ef0, 0xc00109f2f0) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/go/ir/builder.go:2545 +0x189 honnef.co/go/tools/go/ir.(*Package).build(0xc000983ef0) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/go/ir/builder.go:2649 +0xb46 sync.(*Once).doSlow(0xc0015021c0?, 0xc003952420?) /usr/lib/go/src/sync/once.go:74 +0xc2 sync.(*Once).Do(...) /usr/lib/go/src/sync/once.go:65 honnef.co/go/tools/go/ir.(*Package).Build(...) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/go/ir/builder.go:2567 honnef.co/go/tools/internal/passes/buildir.run(0xc0022c0820) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/internal/passes/buildir/buildir.go:86 +0x1b1 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyze(0xc001a9e480) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:190 +0xa02 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func2() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:112 +0x17 github.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0xc000825770, {0x196a615, 0x7}, 0xc000fd9748) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go:111 +0x44 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe(0x0?) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:111 +0x7a github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze.func2(0xc001a9e480) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:80 +0xa8 created by github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze in goroutine 81 /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:75 +0x205 ERRO [linters_context/goanalysis] fact_purity: panic during analysis: interface conversion: interface {} is nil, not *buildir.IR, goroutine 900 [running]: runtime/debug.Stack() /usr/lib/go/src/runtime/debug/stack.go:24 +0x5e github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func1() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:104 +0x5a panic({0x17f37c0?, 0xc002cf6180?}) /usr/lib/go/src/runtime/panic.go:770 +0x132 honnef.co/go/tools/analysis/facts/purity.purity(0xc0005d5e10) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/analysis/facts/purity/purity.go:109 +0x29d github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyze(0xc001a9e3f0) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:190 +0xa02 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func2() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:112 +0x17 github.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0xc000825770, {0x19b4160, 0xb}, 0xc000c97748) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go:111 +0x44 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe(0xc0015edf20?) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:111 +0x7a github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze.func2(0xc001a9e3f0) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:80 +0xa8 created by github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze in goroutine 81 /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:75 +0x205 ERRO [linters_context/goanalysis] nilness: panic during analysis: interface conversion: interface {} is nil, not *buildir.IR, goroutine 849 [running]: runtime/debug.Stack() /usr/lib/go/src/runtime/debug/stack.go:24 +0x5e github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func1() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:104 +0x5a panic({0x17f37c0?, 0xc001e58480?}) /usr/lib/go/src/runtime/panic.go:770 +0x132 honnef.co/go/tools/analysis/facts/nilness.run(0xc00c68d110) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/analysis/facts/nilness/nilness.go:65 +0x277 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyze(0xc001aaff70) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:190 +0xa02 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func2() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:112 +0x17 github.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0xc000825770, {0x196270b, 0x7}, 0xc000fd6f48) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go:111 +0x44 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe(0x0?) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:111 +0x7a github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze.func2(0xc001aaff70) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:80 +0xa8 created by github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze in goroutine 81 /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:75 +0x205 ERRO [linters_context/goanalysis] typedness: panic during analysis: interface conversion: interface {} is nil, not *buildir.IR, goroutine 818 [running]: runtime/debug.Stack() /usr/lib/go/src/runtime/debug/stack.go:24 +0x5e github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func1() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:104 +0x5a panic({0x17f37c0?, 0xc0023fade0?}) /usr/lib/go/src/runtime/panic.go:770 +0x132 honnef.co/go/tools/analysis/facts/typedness.run(0xc0022c1790) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/analysis/facts/typedness/typedness.go:59 +0x21d github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyze(0xc001aae590) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:190 +0xa02 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func2() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:112 +0x17 github.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0xc000825770, {0x1987dff, 0x9}, 0xc001be5f48) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go:111 +0x44 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe(0xc0015edbc0?) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:111 +0x7a github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze.func2(0xc001aae590) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:80 +0xa8 created by github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze in goroutine 81 /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:75 +0x205 ERRO [runner] Panic: S1011: package "main" (isInitialPkg: true, needAnalyzeSource: true): interface conversion: interface {} is nil, not purity.Result: goroutine 838 [running]: runtime/debug.Stack() /usr/lib/go/src/runtime/debug/stack.go:24 +0x5e github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func1() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:108 +0x277 panic({0x17f37c0?, 0xc002cf66c0?}) /usr/lib/go/src/runtime/panic.go:770 +0x132 honnef.co/go/tools/simple.CheckLoopAppend(0xc000031040) /home/ldez/sources/go/pkg/mod/honnef.co/go/tools@v0.4.7/simple/lint.go:795 +0x105 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyze(0xc001a9e360) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:190 +0xa02 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe.func2() /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:112 +0x17 github.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0xc000825770, {0x195ccd5, 0x5}, 0xc000fdd748) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go:111 +0x44 github.com/golangci/golangci-lint/pkg/goanalysis.(*action).analyzeSafe(0x0?) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_action.go:111 +0x7a github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze.func2(0xc001a9e360) /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:80 +0xa8 created by github.com/golangci/golangci-lint/pkg/goanalysis.(*loadingPackage).analyze in goroutine 81 /home/ldez/sources/go/src/github.com/golangci/golangci-lint/pkg/goanalysis/runner_loadingpackage.go:75 +0x205 WARN [runner] Can't run linter goanalysis_metalinter: goanalysis_metalinter: S1011: package "main" (isInitialPkg: true, needAnalyzeSource: true): interface conversion: interface {} is nil, not purity.Result ERRO Running error: can't run linter goanalysis_metalinter goanalysis_metalinter: S1011: package "main" (isInitialPkg: true, needAnalyzeSource: true): interface conversion: interface {} is nil, not purity.Result ``` https://github.com/dominikh/go-tools/issues/1494
pomo-mondreganto commented 2 months ago

@ldez the issue you mentioned is now completed, but on golangci-lint 1.59.1 with goexperiment.rangefunc tag in linter's build tags the linter still fails:

stream/iter_test.go:26:23: cannot range over seq (variable of type iter.Seq2[*int, error])
stream/iter_test.go:44:23: cannot range over seq (variable of type iter.Seq2[*int, error])
stream/iter_test.go:66:23: cannot range over seq (variable of type iter.Seq2[*int, error]) (typecheck)

UPD: I've read that typecheck "is not a real linter but rather reports compilation failures", but this works for me when golangci-lint fails:

go build -tags goexperiment.rangefunc ./...
ldez commented 2 months ago

https://github.com/golangci/golangci-lint/issues/4627#issuecomment-2045476681

pomo-mondreganto commented 2 months ago

Will wait for another month or so then :) (1.23 release should make this non-experiment)