golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.41k stars 17.7k forks source link

cmd/go, x/tools/gopls: misleading errors for invalid import #59433

Open findleyr opened 1 year ago

findleyr commented 1 year ago

Just noticed this while refactoring import paths:

image

In this case, I'm in the process of moving the 'tag' package, and the old location no longer exists. I believe the error message is due to the logic here: https://cs.opensource.google/go/x/tools/+/master:internal/gcimporter/iimport.go;l=218;drc=fa556487c5c2be818dd2bab43e16f1afa06f8f89

The problem is that we're now importing packages with broken metadata, and invalid imports appear to have package path "".

findleyr commented 1 year ago

Oh, this appears to simply be a go/packages bug, as I can reproduce without gopls, using x/tools/go/packages/gopackages.

Note that after removing the tag package, the "CompiledGoFiles" field is simply wrong. It picks up the first compiled go file of the jsonrpc2 package.

CC @adonovan @matloob @bcmills

I have not yet reproduced this with go list alone, so it may be a bug in the go list driver)

> gopackages -json golang.org/x/tools/internal/jsonrpc2 golang.org/x/tools/internal/event/tag
{
    "ID": "golang.org/x/tools/internal/event/tag",
    "PkgPath": "golang.org/x/tools/internal/event/tag",
    "Errors": [
        {
            "Pos": "../internal/jsonrpc2/conn.go:16:2",
            "Msg": "no required module provides package golang.org/x/tools/internal/event/tag; to add it:\n\tgo get golang.org/x/tools/internal/event/tag",
            "Kind": 1
        }
    ],
    "GoFiles": [
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/conn.go"
    ],
    "CompiledGoFiles": [
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/conn.go"
    ]
}{
    "ID": "golang.org/x/tools/internal/jsonrpc2",
    "Name": "jsonrpc2",
    "PkgPath": "golang.org/x/tools/internal/jsonrpc2",
    "GoFiles": [
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/conn.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/handler.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/jsonrpc2.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/messages.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/serve.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/stream.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/wire.go"
    ],
    "CompiledGoFiles": [
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/conn.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/handler.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/jsonrpc2.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/messages.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/serve.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/stream.go",
        "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2/wire.go"
    ],
    "Imports": {
        "bufio": "bufio",
        "context": "context",
        "encoding/json": "encoding/json",
        "errors": "errors",
        "fmt": "fmt",
        "golang.org/x/tools/internal/event": "golang.org/x/tools/internal/event",
        "golang.org/x/tools/internal/event/label": "golang.org/x/tools/internal/event/label",
        "golang.org/x/tools/internal/event/tag": "golang.org/x/tools/internal/event/tag",
        "io": "io",
        "math": "math",
        "net": "net",
        "os": "os",
        "strconv": "strconv",
        "strings": "strings",
        "sync": "sync",
        "sync/atomic": "sync/atomic",
        "time": "time"
    }
}
findleyr commented 1 year ago

Actually, this is a Go command bug. Compare the two go list invocations below. When the jsonrpc2 package is included, the error for internal/event/tag erroneously uses a position from the jsonrpc2 package.

go/packages interprets this error to synthesize missing GoFiles, due to #39986.

> go list -e -json -compiled=true -test=false -export=false -find=false -- golang.org/x/tools/internal/event/tag
{
    "ImportPath": "golang.org/x/tools/internal/event/tag",
    "Match": [
        "golang.org/x/tools/internal/event/tag"
    ],
    "Incomplete": true,
    "Error": {
        "ImportStack": [],
        "Pos": "",
        "Err": "no required module provides package golang.org/x/tools/internal/event/tag; to add it:\n\tgo get golang.org/x/tools/internal/event/tag"
    }
}

vs.

> go list -e -json -compiled=true -test=false -export=false -find=false -- golang.org/x/tools/internal/jsonrpc2 golang.org/x/tools/internal/event/tag
{
    "Dir": "/usr/local/google/home/rfindley/src/tools2/internal/jsonrpc2",
    "ImportPath": "golang.org/x/tools/internal/jsonrpc2",
    "Name": "jsonrpc2",
    "Doc": "Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec.",
    "Root": "/usr/local/google/home/rfindley/src/tools2",
    "Module": {
        "Path": "golang.org/x/tools",
        "Main": true,
        "Dir": "/usr/local/google/home/rfindley/src/tools2",
        "GoMod": "/usr/local/google/home/rfindley/src/tools2/go.mod",
        "GoVersion": "1.18"
    },
    "Match": [
        "golang.org/x/tools/internal/jsonrpc2"
    ],
    "Incomplete": true,
    "Stale": true,
    "StaleReason": "stale dependency: golang.org/x/tools/internal/event/tag",
    "GoFiles": [
        "conn.go",
        "handler.go",
        "jsonrpc2.go",
        "messages.go",
        "serve.go",
        "stream.go",
        "wire.go"
    ],
    "CompiledGoFiles": [
        "conn.go",
        "handler.go",
        "jsonrpc2.go",
        "messages.go",
        "serve.go",
        "stream.go",
        "wire.go"
    ],
    "Imports": [
        "bufio",
        "context",
        "encoding/json",
        "errors",
        "fmt",
        "golang.org/x/tools/internal/event",
        "golang.org/x/tools/internal/event/label",
        "golang.org/x/tools/internal/event/tag",
        "io",
        "math",
        "net",
        "os",
        "strconv",
        "strings",
        "sync",
        "sync/atomic",
        "time"
    ],
    "Deps": [
        "bufio",
        "bytes",
        "context",
        "encoding",
        "encoding/base64",
        "encoding/binary",
        "encoding/json",
        "errors",
        "fmt",
        "golang.org/x/tools/internal/event",
        "golang.org/x/tools/internal/event/core",
        "golang.org/x/tools/internal/event/keys",
        "golang.org/x/tools/internal/event/label",
        "golang.org/x/tools/internal/event/tag",
        "internal/abi",
        "internal/bytealg",
        "internal/coverage/rtcov",
        "internal/cpu",
        "internal/fmtsort",
        "internal/goarch",
        "internal/godebug",
        "internal/goexperiment",
        "internal/goos",
        "internal/intern",
        "internal/itoa",
        "internal/nettrace",
        "internal/oserror",
        "internal/poll",
        "internal/race",
        "internal/reflectlite",
        "internal/safefilepath",
        "internal/singleflight",
        "internal/syscall/execenv",
        "internal/syscall/unix",
        "internal/testlog",
        "internal/unsafeheader",
        "io",
        "io/fs",
        "math",
        "math/bits",
        "net",
        "net/netip",
        "os",
        "path",
        "reflect",
        "runtime",
        "runtime/cgo",
        "runtime/internal/atomic",
        "runtime/internal/math",
        "runtime/internal/sys",
        "runtime/internal/syscall",
        "sort",
        "strconv",
        "strings",
        "sync",
        "sync/atomic",
        "syscall",
        "time",
        "unicode",
        "unicode/utf16",
        "unicode/utf8",
        "unsafe",
        "vendor/golang.org/x/net/dns/dnsmessage"
    ],
    "DepsErrors": [
        {
            "ImportStack": [
                "golang.org/x/tools/internal/event/tag"
            ],
            "Pos": "internal/jsonrpc2/conn.go:16:2",
            "Err": "no required module provides package golang.org/x/tools/internal/event/tag; to add it:\n\tgo get golang.org/x/tools/internal/event/tag"
        }
    ],
    "TestGoFiles": [
        "serve_test.go"
    ],
    "TestImports": [
        "context",
        "golang.org/x/tools/internal/stack/stacktest",
        "golang.org/x/tools/internal/testenv",
        "net",
        "sync",
        "testing",
        "time"
    ],
    "XTestGoFiles": [
        "jsonrpc2_test.go",
        "wire_test.go"
    ],
    "XTestImports": [
        "bytes",
        "context",
        "encoding/json",
        "flag",
        "fmt",
        "golang.org/x/tools/internal/event/export/eventtest",
        "golang.org/x/tools/internal/jsonrpc2",
        "golang.org/x/tools/internal/stack/stacktest",
        "net",
        "path",
        "reflect",
        "testing"
    ]
}
{
    "ImportPath": "golang.org/x/tools/internal/event/tag",
    "Match": [
        "golang.org/x/tools/internal/event/tag"
    ],
    "Incomplete": true,
    "Stale": true,
    "StaleReason": "build ID mismatch",
    "Error": {
        "ImportStack": [
            "golang.org/x/tools/internal/event/tag"
        ],
        "Pos": "internal/jsonrpc2/conn.go:16:2",
        "Err": "no required module provides package golang.org/x/tools/internal/event/tag; to add it:\n\tgo get golang.org/x/tools/internal/event/tag"
    }
}
findleyr commented 11 months ago

Moving this to the backlog, since it's a Go command bug and therefore not particularly actionable for gopls.