Skip to content
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/vet: vet fails when listing files unless all files in the package are listed #24668

Closed
spenczar opened this issue Apr 3, 2018 · 7 comments

Comments

Projects
None yet
6 participants
@spenczar
Copy link
Contributor

commented Apr 3, 2018

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.10.1 darwin/amd64

(also occurs in go1.10 darwin/amd64)

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

darwin/amd64

What did you do?

I ran go vet, passing it a subset of files in a package.

github.com/spenczar/testvet/file1.go:

package main

func f() {}

github.com/spenczar/testvet/file2.go:

package main

func main() {
  f()
}

I ran go vet ./file2.go.

What did you expect to see?

No output, and a 0 exit code.

What did you see instead?

Vet complained that it doesn't know about f, because it's in a file in the same package but which wasn't explicitly listed:

-> % go vet ./file2.go
# command-line-arguments
./file2.go:4:2: undefined: f

This is a change in behavior from go1.9.5. Previously, this would exit with no output and code 0.

Listing files explicitly is important in my case because I have a package which contains some generated code and some hand-written code. The hand-written code references objects in the generated code. I want to vet the hand-written code, but I don't care about vet issues in the generated code.

This issue makes that workflow very difficult, maybe impossible, as I have to list all the files to get things to work.

@rasky

This comment has been minimized.

Copy link
Member

commented Apr 3, 2018

This is how all go tools work (including “go build” for instance). You either don’t give arguments (= current directory), specify a relative path pointing to a package, or specify a list of files that most form a full package.

go vet is now much more precise because it has access to full type information, but it requires to see and vet a whole package.

In your case, assuming you don’t want to fix issues in the generated file, I’d just filter out those files from vet’s output (eg: with grep)

@bcmills

This comment has been minimized.

Copy link
Member

commented Apr 3, 2018

What happens if you pass the -source flag to vet?

@spenczar

This comment has been minimized.

Copy link
Contributor Author

commented Apr 3, 2018

@rasky, could you help me understand why this worked in go1.9 and doesn't in go1.10? Was it a bug that it worked in go1.9?

@bcmills, I get the same error:

-> % go vet -source ./file2.go
# command-line-arguments
./file2.go:4:2: undefined: f
@bcmills

This comment has been minimized.

Copy link
Member

commented Apr 3, 2018

I believe this is related to #21287 and #16086.

For your workflow, could you vet the whole package and filter the output to remove warnings for the generated package?

Moreover, vet is intended to have few or no false-positives. What kinds of warnings are you trying to ignore in the generated code?

@spenczar

This comment has been minimized.

Copy link
Contributor Author

commented Apr 3, 2018

For your workflow, could you vet the whole package and filter the output to remove warnings for the generated package?

I could filter output, yes. I just worry about the fragility of that approach, though; is cmd/vet's text output format considered an API which is protected by compatibility guarantees?

For example, in the output here:

-> % go vet -source ./file2.go
# command-line-arguments
./file2.go:4:2: undefined: f

I suppose what I would do is iterate over every line of output. Discard ones that start with a #. For others, resolve the relative path if one appears at the start of the line (which is always relative to cwd, even if absolute file paths were passed in). If the relative path points to a file I know is generated, discard the line. If no lines remain, exit with code 0, else exit with code 1 and print the lines.

This would work today, but I think it could easily break in the future, unless vet's output is part of the compatibility guarantees.

Moreover, vet is intended to have few or no false-positives. What kinds of warnings are you trying to ignore in the generated code?

Unkeyed composite literals have shown up in github.com/golang/protobuf/protoc-gen-go's output. See golang/protobuf#214. I see now that this has been fixed three weeks ago, though, in golang/protobuf#560, so maybe it's no longer an issue. Maybe I should regenerate and vet all code now.

The reason I want to skip generated files isn't that vet is incorrectly flagging code, though. It's really that I rarely have the ability to fix the problem myself, because the code generator is typically written by someone else. They have to agree that making their generated output pass vet is worthwhile (which isn't always easy!) and then make changes, and then I need to regenerate code.

@bcmills bcmills modified the milestones: Go1.11, Go1.10.2 Apr 4, 2018

@bcmills

This comment has been minimized.

Copy link
Member

commented Apr 4, 2018

I think step 1 is to determine whether vet on an incomplete part of a package is actually supported, or just happened to work by accident prior to 1.10. (I don't actually know the answer to that.)

@rsc

This comment has been minimized.

Copy link
Contributor

commented Apr 9, 2018

I want to vet the hand-written code, but I don't care about vet issues in the generated code.

This is just not supported. Vet works on whole packages. As it gets more sophisticated that's going to become more important. I would suggest grepping away things in generated code, or else writing the generated code in a way that doesn't produce vet errors. The latter (adjusting the generated code) should always be possible. If not, then please open a different issue (and link to it here) for the specific vet error that you can't avoid.

could you help me understand why this worked in go1.9 and doesn't in go1.10? Was it a bug that it worked in go1.9?

Yes, it was a (design) bug. Vet wasn't sophisticated enough to insist, and now it is.

@rsc rsc closed this Apr 9, 2018

@FiloSottile FiloSottile modified the milestones: Go1.10.2, Go1.11 Apr 24, 2018

@golang golang locked and limited conversation to collaborators Apr 24, 2019

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.