golangci-lint
golangci-lint copied to clipboard
typecheck doesn't seem to recognise go:wasmimport directives
Welcome
- [X] Yes, I'm using a binary release within 2 latest releases. Only such installations are supported.
- [X] Yes, I've searched similar issues on GitHub and didn't find any.
- [X] Yes, I've read the
typechecksection of the FAQ. - [X] Yes, I've tried with the standalone linter if available (e.g., gocritic, go vet, etc.).
- [X] I agree to follow this project's Code of Conduct
Description of the problem
Functions that are marked with //go:wasmimport cannot (by design) have a function body. They're simply the declaration for the function that will be imported. However, golangci-lint fails with missing function body (typecheck).
I understand this probably isn't an issue that can be fixed here, but I'm really uncertain where/how to report it elsewhere.
The example program below compiles properly with either Go or TinyGo.
Go:
GOOS=wasip1 GOARCH=wasm go build -o test.wasm
TinyGo:
tinygo build -target=wasip1 -o test.wasm
But it fails linting with golangci-lint. I also tried staticheck, and it fails in a similar way there too.
Please let me know if I should report this elsewhere also. Thanks.
Version of golangci-lint
golangci-lint has version 1.60.3 built with go1.23.0 from c2e095c on 2024-08-22T21:45:24Z
Configuration
Go environment
go version go1.23.0 darwin/arm64
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/matt/Library/Caches/go-build'
GOENV='/Users/matt/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/matt/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/matt/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.23.0/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.23.0/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.23.0'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/matt/Library/Application Support/go/telemetry'
GCCGO='gccgo'
GOARM64='v8.0'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/Users/matt/Code/gotemp/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 -ffile-prefix-map=/var/folders/sf/btdk_dj52jx9lpzxfq01q9d00000gn/T/go-build4013300433=/tmp/go-build -gno-record-gcc-switches -fno-common'
Verbose output of running
INFO golangci-lint has version 1.60.3 built with go1.23.0 from c2e095c on 2024-08-22T21:45:24Z
INFO [config_reader] Config search paths: [./ /Users/matt/Code/gotemp /Users/matt/Code /Users/matt /Users /]
INFO [lintersdb] Active 6 linters: [errcheck gosimple govet ineffassign staticcheck unused]
INFO [loader] Go packages loading at mode 575 (types_sizes|exports_file|name|files|imports|compiled_files|deps) took 130.07175ms
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 404.458µs
INFO [linters_context/goanalysis] analyzers took 3.235584ms with top 10 stages: buildir: 499.333µs, fact_deprecated: 467.917µs, ifaceassert: 118.667µs, S1012: 92.125µs, inspect: 81µs, directive: 66.125µs, S1017: 64.417µs, ineffassign: 62.834µs, cgocall: 52.708µs, S1002: 50.875µs
INFO [runner] Issues before processing: 175, after processing: 1
INFO [runner] Processors filtering stat (in/out): diff: 1/1, source_code: 1/1, nolint: 175/175, max_from_linter: 1/1, path_shortener: 1/1, filename_unadjuster: 175/175, skip_files: 175/175, exclude: 175/175, max_per_file_from_linter: 1/1, max_same_issues: 1/1, severity-rules: 1/1, path_prefixer: 1/1, sort_results: 1/1, cgo: 175/175, invalid_issue: 175/175, path_prettifier: 175/175, skip_dirs: 175/175, autogenerated_exclude: 175/175, identifier_marker: 175/175, exclude-rules: 175/175, uniq_by_line: 175/1, fixer: 1/1
INFO [runner] processing took 2.059ms with stages: identifier_marker: 1.389708ms, skip_dirs: 372.667µs, path_prettifier: 207.167µs, source_code: 28.416µs, autogenerated_exclude: 20.167µs, nolint: 15.542µs, uniq_by_line: 5.083µs, invalid_issue: 4.833µs, filename_unadjuster: 4.666µs, cgo: 4.542µs, exclude-rules: 2.583µs, max_same_issues: 1.333µs, path_shortener: 792ns, max_from_linter: 292ns, skip_files: 292ns, exclude: 209ns, sort_results: 208ns, max_per_file_from_linter: 208ns, fixer: 167ns, severity-rules: 84ns, diff: 41ns, path_prefixer: 0s
INFO [runner] linters took 14.731083ms with stages: goanalysis_metalinter: 12.599834ms
main.go:1: : # main
./main.go:10:6: missing function body (typecheck)
package main
INFO File cache stats: 1 entries of total size 134B
INFO Memory: 3 samples, avg is 28.1MB, max is 30.9MB
INFO Execution took 151.832167ms
A minimal reproducible example or link to a public repository
package main
func main() {
result := add(1, 2)
println(result)
}
//go:noescape
//go:wasmimport foo add
func add(a, b int32) int32
Validation
- [X] Yes, I've included all information above (version, config, etc.).
Supporter
- [ ] I am a sponsor/backer through GitHub or OpenCollective
Hey, thank you for opening your first Issue ! 🙂 If you would like to contribute we have a guide for contributors.
You need to define the build tags inside the configuration:
run:
build-tags:
- wasip1
Also, it's not needed but you can additionally add build tags inside your code:
//go:build wasip1
package main
func main() {
result := add(1, 2)
println(result)
}
//go:noescape
//go:wasmimport foo add
func add(a, b int32) int32
Perfect. Thank you!
@ldez - there's still something slightly off. If I have everything in one main.go file and add the build tag to the run configuration it lints correctly. But if I move the imported function to a sub package, it fails again.
.golangci.yml
run:
build-tags:
- wasip1
go.mod
module main
go 1.23.0
main.go
package main
import "main/foo"
func main() {
result := foo.Add(1, 2)
println(result)
}
foo/add.go
package foo
//go:noescape
//go:wasmimport foo add
func Add(a, b int32) int32
output from golangci-lint run
foo/add.go:1: : # main/foo
foo/add.go:5:6: missing function body (typecheck)
package foo
main.go:5:8: could not import main/foo (-: # main/foo
foo/add.go:5:6: missing function body) (typecheck)
import "main/foo"
Adding the build tag directly in the file doesn't seem to help.
as a workaround, you can play with build tags.
You can remove the build tags from the golancgi-lint configuration and use the following pattern:
main.go
package main
import "github.com/golangci/sandbox/foo"
func main() {
result := foo.Add(1, 2)
println(result)
}
foo/add.go
//go:build wasip1
package foo
//go:noescape
//go:wasmimport foo add
func Add(a, b int32) int32
foo/add_fake.go
//go:build !wasip1
package foo
func Add(a, b int32) int32 {
return a + b
}
Ok. I can do that for now. Did you want to re-open this then? Or is it an issue for Go itself?
For now, I don't know where is the problem. I have several topics to handle at the same time (like these spam bots that come on every new issue) so I'll analyze the problem as quickly as possible, but "time is a limit". :wink:
Understood. Thank you.
FYI, the workaround with build tags in separate files is actually working quite nicely for me. I can use the "fake" one for mocking the imported functions in unit tests. I think this is the way. 😄
Does golangci-lint have configurations to skip directories? I tested exclusions.paths, but unfortunately, it doesn't work.
Does golangci-lint have configurations to skip directories? I tested
exclusions.paths, but unfortunately, it doesn't work.
You mean instead of using build tags?
Build tags is one way, but exclusions won't change what's analyzed, just what's reported. See #5438 and #5297
Yes, without using build tags. I'm looking for a feature to skip the entire directories including analyzing. I suppose golangci-lint doesn't support this yet.