-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
cmd/go: build required dependencies for 'go vet' type information #16086
Comments
go1.7beta1 seems to be broken in the opposite way, which is even more worrying:
I guess there could be something funky with |
cmd/vet makes some decisions based on types. When the type is defined in some other package, cmd/vet tries to determine the type by looking at the installed packages. This has the fortunate consequences of better results, but the unfortunate consequence of results that are harder to reproduce. In this case you can see that the types in question are in different packages. The vet warning Closing because this is expected behavior. Please feel free to comment if you disagree. |
Ah, I see my understanding of this particular problem is out of date thanks to issue #9171. In 1.7 we are more careful about issuing this warning for unknown types. I'm not sure why the 1.7 warnings are not issued for 1.6. Are the warnings correct? |
Now that I'm looking more closely, yes, the warnings in 1.6 are incorrect. type Annotations []Annotation
type annotations Annotations
type Annotation struct {
Name ACIdentifier `json:"name"`
Value string `json:"value"`
} and it's used like Annotations: appctypes.Annotations{
appctypes.Annotation{
Name: *appctypes.MustACIdentifier(k8sRktKubeletAnno),
Value: k8sRktKubeletAnnoValue,
},
appctypes.Annotation{
Name: *appctypes.MustACIdentifier(types.KubernetesPodUIDLabel),
Value: podUID,
},
[etc] which seems valid.
Exec: appctypes.Exec{"/bin/foo", "bar"}, The 1.7 warnings look legitimate, too. type Environment []EnvironmentVariable
type environment Environment
type EnvironmentVariable struct {
Name string `json:"name"`
Value string `json:"value"`
} One of the failing lines looks like Environment: []appctypes.EnvironmentVariable{
{"env-foo", "bar"},
}, which is definitely using unkeyed fields. I guess my only complaint then is that |
I will reopen the issue as a request that cmd/vet rebuild dependencies. That can not be a required behavior, as people use cmd/vet to check incomplete code and dependencies may not be available. But I think it would be an optional behavior. |
sounds great, thanks! |
IIUC, it's not a question of rebuilding dependencies but of re-typechecking them, at least when source code is available. This is generally desirable, since it avoids these kinds of problems, and go/types is fast. There's a similar issue and discussion around stringer: #10249. The permanent answer here is to get go/loader's API fixed up and have vet use it. I'm not sure where that project stands. |
go vet should probably use a source-based importer for for go/types so that its dependencies are as up-to-date as possible. |
If/when go vet uses a source-based importer, the vet-the-core runner currently in CL 27811 should be updated not to do |
+1 to using source-based importer. We were running For reference, here's a self-contained test that demonstrates the issue (wrote it with the intent of including it in a bug before finding this issue): package main_test
import (
"io/ioutil"
"os"
"os/exec"
"path"
"testing"
)
const (
testMain = `package main
import "github.com/nmiyake/govetbug/testprint"
func main() {
testprint.Print("hello, %v!", "world")
}
`
testPrint = `package testprint
import "fmt"
func Print(msgAndArgs ...interface{}) {
if len(msgAndArgs) == 0 {
return
}
fmt.Printf(msgAndArgs[0].(string), msgAndArgs[1:]...)
}
`
)
// (1) Create a file that calls a "Print" function in another package in a manner that should trigger a go vet error
// (2) Run "go vet ." on the project
//
// Expected: go vet issues are reported
// Actual: go vet reports no failures
//
// (4) Run "go install ./..." on the project
// (5) Run "go vet ." on the project
//
// Expected: output/behavior is the same as running after (2)
// Actual: go vet now reports the failures as originally expected
func TestGoVet(t *testing.T) {
// create tmpDir to act as test GOPATH
tmpDir, err := ioutil.TempDir("", "")
if err != nil { panic(err) }
defer os.RemoveAll(tmpDir)
err = os.Setenv("GOPATH", tmpDir)
if err != nil { panic(err) }
// write test print file
testPrintDir := path.Join(tmpDir, "src/github.com/nmiyake/govetbug/testprint")
err = os.MkdirAll(testPrintDir, 0755)
if err != nil { panic(err) }
err = ioutil.WriteFile(path.Join(testPrintDir, "testprint.go"), []byte(testPrint), 0644)
if err != nil { panic(err) }
// write out test main file
testMainDir := path.Join(tmpDir, "src/github.com/nmiyake/govetbug")
err = ioutil.WriteFile(path.Join(testMainDir, "main.go"), []byte(testMain), 0644)
if err != nil { panic(err) }
cmd := exec.Command("go", "vet", ".")
cmd.Dir = testMainDir
output, err := cmd.CombinedOutput()
// Expect "possible formatting directive in Print call" error, but does not occur
if err != nil {
t.Errorf("%v failed: %v", cmd.Args, string(output))
}
// install the package
cmd = exec.Command("go", "install", "./...")
cmd.Dir = testMainDir
output, err = cmd.CombinedOutput()
if err != nil {
t.Errorf("%v failed: %v", cmd.Args, string(output))
}
cmd = exec.Command("go", "vet", ".")
cmd.Dir = testMainDir
output, err = cmd.CombinedOutput()
// "possible formatting directive in Print call" is reported after "go install ./..." is run
if err != nil {
t.Errorf("%v failed: %v", cmd.Args, string(output))
}
} |
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`.
We could make the go command just build the necessary pieces and pass the path to tool vet, like it does for, say, go test or go build. We probably should. But not for Go 1.8. |
CL https://golang.org/cl/36992 mentions this issue. |
I think we should have vet typecheck from source. The compiler is much slower than go/types--it has to do lots more work. |
It's a 1.9 item for me to compute package information from source for gotype, if it's not present. See #11415. |
As noted by griesemer in golang/go#18799, this doesn't address the issues raised in golang/go#11415 because when checking an xtest package the corresponding package is assumed to have been installed. This however is similar to the assumptions made by go vet (raised as an issue in golang/go#16086). So whilst not perfect, it will probably suffice until golang/go#11415 is resolved. Fixes golang/go#18799 Change-Id: I1ea005c402e5d6f5abddda68fee6386b0531dfba Reviewed-on: https://go-review.googlesource.com/36992 Reviewed-by: Robert Griesemer <gri@golang.org>
#11415 is now fixed. This issue can go ahead now. |
I disagree that vet should use source. In a large tree, you can cache the 'go build' output. |
@rsc can I at least add a -source flag to 'go tool vet', to force it into read-from-source mode? |
CL https://golang.org/cl/37690 mentions this issue. |
Add a -source flag to cmd/vet that instructs it to typecheck purely from source code. Updates #16086 Fixes #19332 Change-Id: Ic83d0f14d5bb837a329d539b2873aeccdf7bf669 Reviewed-on: https://go-review.googlesource.com/37690 Reviewed-by: Rob Pike <r@golang.org>
go vet relies on some type information extracted from installed archives. See golang/go#16086 for details. Signed-off-by: Maciej Borzecki <maciej.borzecki@rndity.com>
Vet will need even more work along these lines with the new caching work planned for Go 1.10. But then things will be better, and this will be fixed. See also #17571. |
@rsc I think you may have linked to the wrong issue? |
Thanks, fixed link - #17571. |
Today using go 1.8.3 and |
Change https://golang.org/cl/74356 mentions this issue: |
Change https://golang.org/cl/74750 mentions this issue: |
Quick summary:
go vet
currently fails on some code in the Kubernetes repo.After running
go install
, however,go vet
no longer fails - possibly because it's not building the code anymore?go version
)?go env
)?go vet
should've still failed aftergo install
.go vet
passed, until intermediate compilation artifacts were removed.cc @mikedanese who first discovered this.
The text was updated successfully, but these errors were encountered: