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
U1000 error for unused functions which are used in skipped test #633
Comments
The reason this changed is because staticcheck is now "smarter", recognizing that no code after t.Skip will execute. This effectively makes the rest of TestSum invisible to U1000, which means I'll have to think about this specific case and whether we need to work around it. |
Thanks for replying. I think changing test case to skip may happen quite often because of some other dependency failure, and developers don't have time to investigate temporarily. In this case, people probably don't want to see other static check failure because of the change. Just my 2 cents. |
This flags a couple of things in our repo too. |
(but that is very clever analysis!) |
Hi! Do you think you can do something about this? We are using |
Unfortunately there isn't a quick and easy fix for this. It will require fundamental changes to the implementation of the check. I do have these changes on my todo list, but it will take months until I get to it. In the meantime, you will have to make use of the various ways of ignoring problems – disabling the check, ignoring the specific instances you consider wrong (via |
Marking every dependency of a skipped test with var skip = func(t *testing.T) {
t.SkipNow()
}
func TestCurrentlyDisabled(t *testing T) {
skip(t)
...
} This way, |
Okay, I have two options:
Option 1 would be an annoying amount of work, and constitute the third (or fourth? I can't remember) full rewrite of Option 2 is a quick and easy fix, but it is not localized to Option 2 is also specific to SkipNow. If you have other patterns of skipping over code, such as calling runtime.Goexit yourself, or panicking, possibly not even in test code, then we would still remove the unreachable code and mark things as unused. In other words, the check would still be based on the effective IR, not the code's syntactic form. I believe limiting it to SkipNow is fine. I've only ever seen people complain because of SkipNow, but it's also why I'm writing this comment: so anyone who ran into this issue, but not because of t.SkipNow, can speak up. |
I've only experienced this problem with SkipNow.
This would be fine for me, because I don't use SkipNow to guard completely broken code (I would comment it out or delete it). Other people might, I suppose. I didn't expect unused to understand that SkipNow prevents subsequent code from running and make inferences based on that, so I think the flip side of that is that if it starts flagging new stuff in skipped tests, it shouldn't be too surprising for people or hard to understand. |
Option 3 would be to invent a way to declare that a certain function does not return, e.g. in a special comment. |
We already know when a function doesn't return. That's why this issue exists in the first place. During IR construction, we note that any code after a call to SkipNow (and variations that call SkipNow) is unreachable and remove it. Which is why the That is,
translates to
Subsequently, Thus we arrive at the two options: implement the check in terms of the AST, or pretend that SkipNow returns. |
How do you know that about |
There is a known list of functions that terminate the process or the goroutine, and we hard-code that list. This is syscall.Exit, runtime.Goexit, and some runtime-internal functions (such as runtime.throw). Almost all other information derives from those basis functions. If a function unconditionally calls runtime.Goexit, then we know that it won't return, and so on. I say almost because there is a list of hand-coded rules for functions where we cannot detect that they call either due to some conditionals, mostly in logging libraries. It is trivial to extend this list to treat SkipNow as a function that does return. The problem here isn't implementing option 2, but deciding whether option 2 is the right approach. The implementation is as simple as adding a new Line 9 in f5dad99
|
So, any good workaround for this? |
#633 (comment) contains one workaround for now. |
I would be supportive of landing the change to special case |
I just ran into this. The issue, I think, is that it seems weird to call a function "unused" if you can't compile without it. I think there's a distinction to be had here between "isn't used" in the sense of "doesn't matter to program output" and "isn't used" in the sense of "doesn't matter to program compilation". |
Note that I am fully aware that the current behavior is bad, I don't need to be convinced of that. This problem, and most of the other problems of U1000, are caused by us using our IR to implement it, even though it's not an ideal fit for the problem. The quick workaround on our end would be to give special treatment to the Skip function. But this will a) affect other checks negatively b) only fix this specific instance of the problem. The proper solution is to reimplement the check and operate on a representation that is closer to the actual source code. Doing so is near the top of my todo list. |
Thanks for the great tool, and we used it in our CI heavily. Just from last Friday, our CI got broken because that static check starts complaining U1000 error for unused functions which are used in skipped test. Below are sample codes which are reproducible. The running commands is
staticcheck .
. Every CI run we get the latest tool throughgo get -u honnef.co/go/tools/cmd/staticcheck
For now, we have to add
lint:file-ignore U1000 Ignore report
to skip the error. Please let me know if something is changed recently. Thanks again.The text was updated successfully, but these errors were encountered: