-
Notifications
You must be signed in to change notification settings - Fork 18k
x/tools/cmd/stringer: can't find packages #10249
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
Comments
Have you tried "go install a/b" before running stringer?
|
Ok, that works. Why? |
Stringer packages to be installed so it can parse and type check the files it's reading. |
stringer uses go/types, which uses go/loader to find packages. There are multiple strategies for finding packages available. Stringer uses gcimporter, which parses gc's object files. If the package has not been installed, the object files are not available to parse. |
So this should be documented somewhere, perhaps at https://godoc.org/golang.org/x/tools/cmd/stringer |
It's not a property of stringer per se. You can't build or parse (actually type check) a package without building (or parsing) its dependencies first. Any tool that looks at types has the same property. It's the nature of the work. |
So shouldn't stringer build its dependencies if they haven't been built yet? Or at least parse them if it can't find a built object file? Or give me a better error message than "could not import a/b (can't find import: a/b)", like "could not import a/b (it must be built first)"? |
@randall77 I agree entirely, but this is a broader problem than just stringer. Filed #10276 for this. |
For the record: This CL https://go-review.googlesource.com/#/c/8561/ changes stringer to use go/loader, which loads the entire program from source code, so it gets the correct result no matter what compiler you use or how fresh your .a cache is. The change has been mothballed pending a clean-up of the go/loader API (some of which has already happened). |
What's the status on this? Will this not be implemented, or will this be addressed somewhere else (the Go gerrit seems to suggest this was abandoned altogether)? |
for the record, i'm still getting As a side note, I think forcing a |
Don't hold your breath: it will likely be several months before I agree that using compiler export data is rarely the right solution for analysis tools; source is the ground truth (and provides better diagnostic information such as locations for types and functions). The set of installed packages is usually very stale. |
@alandonovan where can I find the blocking |
other stringer fails due to: golang/go#10249 Signed-off-by: Madhav Puri <[email protected]>
I know this problem isn't specific to stringer, but I just spent ages trying to track it down before realizing that it's using |
All packages need to be installed before we can run (some) of the checks and code generators reliably. More precisely, anything that using x/tools/go/loader is fragile (this includes stringer, vet and others). The blocking issue is golang/go#14120; see golang/go#10249 for some more concrete discussion on `stringer` and golang/go#16086 for `vet`.
Reopening because the fixing CL was reverted. |
Change https://golang.org/cl/121884 mentions this issue: |
Reverting that CL just broke any code that assumed stringer was safe to run without running I know that x/tools is not subject to the standard compatibility promise, but we'd lived with slow stringer for a year. Couldn't we have waited a few more months for go/packages to land? Or put the fast-but-broken importer behind a flag, like And when I say "broken," I understand that it's working as designed. I mean that it has a very hostile design. Running |
"Reverting that CL just broke any code that assumed stringer was safe to run without running go install -i first. " No it didn't, only some code, while not reverting it broke mine. The situation is unfortunately very messy. I for one have never run go install -i, not once. It's not just that stringer was slow, it's that it didn't work as it was supposed to. It's meant to create code; requiring the package it writes into to be fully correct beforehand is putting the cart before the horse. The idea behind stringer (other than being a plaything to test out "go generate") was that it would pick up some half-written code with a constant type defined and add a file that helps the package along. But various steps along the way, along with a lack of initial insight, have broken that intention by requiring the package it's in to be valid beforehand. There is a fundamental conflict going on here. I doubt that go/packages will fix it, since I presume it too will require a complete type-checkable package before stringer will run. I thought the resolution would be to go back to the beginning and roll out as much as possible of the dependence on types. Evaluation of constants would then require avoiding type checking and adding its own evaluator. I haven't done that yet; one reason is that in general one might have to look at another package to do that, for cases like It's possible there is literally no clean way to resolve this. We could roll back my recent changes, and maybe should do so, but the original problem would then remain unaddressed. |
Can we not simply loosen the requirement that the target fully type checks? e.g.: https://go-review.googlesource.com/c/tools/+/122377 That way we can leverage the constant evaluation code etc in Same approach could be followed with The above CL allows the following to generate successfully: package main
//go:generate stringer -type Banana
type Banana uint
const (
B1 Banana = iota
)
var x Apple
func main() {
} whereas with the current
|
I doubt that go/packages will fix it, since I presume it too will require a complete type-checkable package before stringer will run.
go/packages is intended to be robust to metadata, syntax, and type errors in any given package and to record them in the returned Package. There are undoubtedly bugs but they should be fixable.
BTW, I measured the speed of go/packages doing the operation needed by the frustratingly slow 4s run of stringer discussed in another issue---I forget the package but it was gopkg.in/something---and it took under 300ms, so it should be fast enough even though it does some type-checking.
|
No, it subtly broke all code and workflows that do not involve running some equivalent of If I have a file in package github.com/benesch/stringertest/b like this package b
type Garbage int
const (
FooGarbage Garbage = iota
BarGarbage
) I can run diff --git a/b/b.go b/b/b.go
index ebfda0e..3c9bcb7 100644
--- a/b/b.go
+++ b/b/b.go
@@ -1,8 +1,11 @@
package b
+import "github.com/benesch/stringertest/a"
+
type Garbage int
const (
FooGarbage Garbage = iota
BarGarbage
+ BazGarbage = a.Sym
) Now stringer fails because github.com/benesch/stringertest/a is not installed: $ stringer -type=Garbage
stringer: checking package: b.go:3:8: could not import github.com/benesch/stringertest/a (can't find import: "github.com/benesch/stringertest/a") There are two ways to resolve this. I can run This was not a problem when stringer used the source importer. Here, github.com/benesch/stringertest/a is not installed, and source-importer stringer succeeds: $ (cd $GOPATH/src/golang.org/x/tools && git checkout ffe8890^ && go install ./cmd/stringer)
$ stringer -type=Garbage
# success
Yes, which is why you ran into the "could not import" error when trying to use stringer: #25650 (comment)
There are two orthogonal issues that are being conflated in this discussion. The first issue is how stringer loads a package's dependencies. The second is what sort of type checking stringer performs, if any. I don't see why the first issue has any bearing on the second. Your change to pass |
With great reluctance, I will roll back my changes and pray that Alan Donovan's work will fix this, if only to shut down this conversation. I do believe there is a deep problem here that only I am worried about, but then if it's only me that worries about it, I guess it doesn't matter much. |
Change https://golang.org/cl/122535 mentions this issue: |
Roll back my two recent changes. Stringer is now very slow again, but works in most use cases. My git foo is insufficient to do this as a revert, but it is a by-hand reversion of CLs https://go-review.googlesource.com/121884 https://go-review.googlesource.com/121995 See the issue for a long conversation about the general problem. Update golang/go#10249 Update golang/go#25650 Change-Id: I7b6ce352a4c7ebf0977883509e9d7189aaac1251 Reviewed-on: https://go-review.googlesource.com/122535 Run-TryBot: Rob Pike <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
Thanks. It's appreciated.
I'm also worried about this problem now that you've raised it, so that makes at least two of us. As I've mentioned elsewhere, I think https://go-review.googlesource.com/c/121995/ is a step in the right direction and I hope you'll resubmit it. |
Revert "cmd/stringer: use source importer when available" This reverts CL 40403. The idea is to avoid type-checking and use just parsing, which should be enough for stringer. Separately reopening golang/go#10249 because the original change closed that issue, but the change is itself causing other problems as described in the discussion at golang/go#25650. This reversion restores the old behavior of stringer and will be followed with other fixes if they can be worked out. Change-Id: I8404d78da08043ede1a36b0e135a3fc7fdf6728d Reviewed-on: https://go-review.googlesource.com/121884 Reviewed-by: Ian Lance Taylor <[email protected]>
This means that running stringer should always have the intended effect, without having to go install the package first, which was a common source of confusion. The source importer is marginally slower, but stringer is run infrequently, and we're only typechecking one package (and fmt), not an entire tree, as vet does. Fixes golang/go#10249 Change-Id: Ib8cde29bd6cc596964dbe7348065932dd59075fc Reviewed-on: https://go-review.googlesource.com/40403 Run-TryBot: Josh Bleecher Snyder <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Daniel Martí <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
Revert "cmd/stringer: use source importer when available" This reverts CL 40403. The idea is to avoid type-checking and use just parsing, which should be enough for stringer. Separately reopening golang/go#10249 because the original change closed that issue, but the change is itself causing other problems as described in the discussion at golang/go#25650. This reversion restores the old behavior of stringer and will be followed with other fixes if they can be worked out. Change-Id: I8404d78da08043ede1a36b0e135a3fc7fdf6728d Reviewed-on: https://go-review.googlesource.com/121884 Reviewed-by: Ian Lance Taylor <[email protected]>
Roll back my two recent changes. Stringer is now very slow again, but works in most use cases. My git foo is insufficient to do this as a revert, but it is a by-hand reversion of CLs https://go-review.googlesource.com/121884 https://go-review.googlesource.com/121995 See the issue for a long conversation about the general problem. Update golang/go#10249 Update golang/go#25650 Change-Id: I7b6ce352a4c7ebf0977883509e9d7189aaac1251 Reviewed-on: https://go-review.googlesource.com/122535 Run-TryBot: Rob Pike <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
This means that running stringer should always have the intended effect, without having to go install the package first, which was a common source of confusion. The source importer is marginally slower, but stringer is run infrequently, and we're only typechecking one package (and fmt), not an entire tree, as vet does. Fixes golang/go#10249 Change-Id: Ib8cde29bd6cc596964dbe7348065932dd59075fc Reviewed-on: https://go-review.googlesource.com/40403 Run-TryBot: Josh Bleecher Snyder <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Daniel Martí <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
Revert "cmd/stringer: use source importer when available" This reverts CL 40403. The idea is to avoid type-checking and use just parsing, which should be enough for stringer. Separately reopening golang/go#10249 because the original change closed that issue, but the change is itself causing other problems as described in the discussion at golang/go#25650. This reversion restores the old behavior of stringer and will be followed with other fixes if they can be worked out. Change-Id: I8404d78da08043ede1a36b0e135a3fc7fdf6728d Reviewed-on: https://go-review.googlesource.com/121884 Reviewed-by: Ian Lance Taylor <[email protected]>
Roll back my two recent changes. Stringer is now very slow again, but works in most use cases. My git foo is insufficient to do this as a revert, but it is a by-hand reversion of CLs https://go-review.googlesource.com/121884 https://go-review.googlesource.com/121995 See the issue for a long conversation about the general problem. Update golang/go#10249 Update golang/go#25650 Change-Id: I7b6ce352a4c7ebf0977883509e9d7189aaac1251 Reviewed-on: https://go-review.googlesource.com/122535 Run-TryBot: Rob Pike <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
I've come here from #24661 via https://go-review.googlesource.com/c/tools/+/126535 and #25650 (comment). Although this issue is closed, the problem still exists in |
I'm having a problem using stringer with go generate. It reports errors because it can't find packages that I think it should be able to find. go build has no trouble finding them.
a.go, in directory $GOPATH/src/a:
package a
import "a/b"
type A int
const (
Aone A = 1
Atwo = 2
Athree = 3
)
//go:generate stringer -type=A
func a() {
b.B()
}
b.go, in directory $GOPATH/src/a/b:
package b
func B() {
}
In $GOPATH/src/a, this happens:
Running go build instead of go generate works fine.
The text was updated successfully, but these errors were encountered: