-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
go/internal/gcimporter: does not support loading vendor packages in std with a lookup func #44630
Comments
Here is where I found the bug: burrowers/garble#236 As you might expect, the fix is: if we're typechecking a std package, use the default importer rather than our custom importer with a lookup func. That works, but it's unfortunate that it's inconsistent and requires a workaround. |
Forgot to cc @findleyr since he's been working on go/types recently. |
This comment has been minimized.
This comment has been minimized.
So I think we both agree that this is something to fix in I'd love to help fix this issue, though I'm not sure how to proceed unless a |
A couple comments. A lot of this is new to me, so my opinions are not particularly informed.
@mvdan: This is a go/types bug, specifically #43119. It should get fixed for 1.17.
@bcmills: Keying off the phrase 'at the moment': is this subject to change?
@mvdan not sure if you meant that the code change belongs in go/types, but go/types should not need to know what the main module is: IIUC since this information is constant throughout the the typechecking pass, is only needed for importing, and is otherwise unnecessary for type checking, it should be closed over by the importer as @bcmills suggests. I don't think the comment Perhaps it would be possible to wrap importer.ForCompiler(...) and mutate import paths following the |
Great, thank you.
I did come to the conclusion that the fix probably belongs in go/types, simply by elimination that I could not find a bug to fix in any of the importer packages (and assuming that we don't want new API). But I'm not familiar with how go/types deals with importing packages internally, so I'm leaving that to the maintainers. |
I tried re-running my tests with |
@findleyr, my comment in #44630 (comment) is no longer correct as of CL 297869, so I'm going to rewrite it here with the up-to-date version. If you are working in a module within GOROOT/src, then the dependencies in the vendor directory of that module are mostly treated as ordinary packages in the standard library, with the prefix
So in order to obtain the correct canonical name for an import, you need to know two things:
The |
Change https://golang.org/cl/310036 mentions this issue: |
I ended up fixing this on my side by wrapping the Does this feel like the right solution overall? If so, then the logical next question is - should we document the need for the creator of the importer to wrap it if using a lookup func? It took me months to arrive at that conclusion, and even though it works I'm still not sure that the API is meant to be used that way. If the answer is "yes, you are meant to take care of this yourself", I think we need better docs, or ideally an API that is harder to misuse. |
I honestly don't know how |
This happens with both
go version devel +e25040d162 Fri Feb 26 02:52:33 2021 +0000 linux/amd64
andgo version go1.16 linux/amd64
. This will be a bit long, as it took me a while to fully understand what's going on.Take the following main program: https://play.golang.org/p/tT_ocdRrssx
It parses and typechecks the
crypto/ecdsa
package in two ways. Note that this package is special, because it imports two vendoredgolang.org/x/crypto
packages:First, we try using
importer.ForCompiler(fset, "gc", nil)
. This works fine; when no lookup func is used, it calls https://golang.org/pkg/go/internal/gcimporter/#FindPkg, which works well.Second, we try using the same as the above, but with a custom lookup func. The custom lookup func is backed by a single
go list -json -deps -export
call before typechecking begins. I'm fairly certain this should work, because thego list
call returns all information needed, and because I can correctly resolve the lookup of those vendored packages.However, the second method fails to typecheck:
The error message is ambiguous, which perhaps is a go/types bug. I use the following patch on Go master to get more details on what's going on:
Now, we get:
Two important things to note here.
First, the error is because the constant comes from the package
golang.org/x/crypto/cryptobyte/asn1
, while the argument type comes from the packagevendor/golang.org/x/crypto/cryptobyte/asn1
. The first is wrong, as it's lacking thevendor/
prefix. In the first method, both end up with the vendor prefix; this is required, because a Go module can also import the actualgolang.org/x/crypto/cryptobyte/asn1
package from the real module, and that needs to be a separate import path from the std-vendored version.Second, note that the first method ends up importing both golang.org/x/crypto packages with the
vendor/
prefix, but the second method does not. Our lookup func does return the right export data file thanks to ImportMap, but since we can only return the file, we cannot tell gcimporter what import path the original path should be replaced with.In the source of
gcimporter.Import
, here's why the "missing lookup func" case works;id
is the canonical import path for the package that is being imported:FindPkg
correctly returnsid = "vendor/golang.org/x/crypto/cryptobyte/asn1"
forpath = "golang.org/x/crypto/cryptobyte/asn1"
.However, in the case where the lookup func is specified, gcimporter forces
id = path
:There is a comment explaining this inconsistency, but I still think there's a bug somewhere. The code calling
gcimporter.Import
is not my code, it's go/types. So it appears that if the bug is not ingcimporter
, and it's on the caller to canonicalize the import path - thengo/types
has a bug as it is not doing that.cc @griesemer @alandonovan as owners
The text was updated successfully, but these errors were encountered: