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
x/tools/cmd/deadcode: add a way to treat exposed APIs as reachable #66073
Comments
I should also note that |
We could define an -exported flag that added all public symbols from non-internal packages of the initial module to the analysis' set of reachable functions. But what can we conclude about func and interface values among the parameters to those functions? Consider
I'm confused: if it is still tested in its own package, wouldn't this be included in |
I'm not sure. I'd be fine with this mode having documented caveats if there's no good way to deal with those situations. Would there be a way to skew towards being conservative in cases like this, leaning towards false negatives rather than false positives?
My understanding and limited experience with the tool is that |
Let's define the terms to ensure we're on the same page: in this context "conservative" means silent and a "positive" is an "unreachable" diagnostic. I think you're asking for the -exported flag to treat all implementations of I as reachable. It could do that, but I think it would seriously degrade precision.
That's correct.
Obviously the tool can't safely report a function as dead if it's needed by a test. Are you saying that -test generates unwanted "coverage", and that you want to know which functions are unreachable from the exported API, ignoring tests? I might still argue that the tool is pointing to a gap in your test suite (though pragmatically I get that a broad shallow API doesn't always need exhaustive test coverage). |
Correct.
Fair enough. I personally wouldn't mind false positives (unreachable diagnostics where I can't remove a declaration without breaking users) assuming they would be relatively rare. I think they should be relatively rare, because the types implementing a public interface are usually also public themselves.
I worry that my bringing up of One tangential thought is that runnable examples could matter in this |
Note Deadcode tool is quite useful, particularly when modularizing the codebase. It assists in breaking down complex functions into smaller, more manageable parts. |
@adonovan What if we additionally add all types reachable from exported types in the transitive reachable packages as live. Would we still have an example that could end up confusing? In particular for the tool to report some F as dead in one set of packages, but not in another? It may be a lack of imagination, but I am struggling to come up with such an example. (TypeParams seem horrible without a whole program though.) |
@alandonovan the deadcode tool is great, thank you so much for working on it! It's being really useful as an extension of staticcheck's unused analysis, which is easier and faster to run, but only works on a per-package basis and doesn't consider exported declarations.
When I run it on a public Go module, such as https://github.com/mvdan/sh, I see a lot of output that doesn't seem right to me:
It's true in some way that these funcs are not reachable; there are only a couple of main packages under
cmd
, and neither use any of those funcs. However, this is a public and stable Go module (https://pkg.go.dev/mvdan.cc/sh/v3) and all of the APIs listed above are exposed on purpose for library users, and cannot be deleted in a backwards compatibility manner even if I wanted to.I wish there were a way to run the deadcode tool in a "library" mode, so that any exposed API would automatically be marked as reachable. I think that would mean any exported names in packages which are not declared as internal.
One could argue that this should happen automatically, for example if the tool can detect it is running on a module which is already a stable semver version like v1 or v3. However, I think being in control would be most useful. Taking my own sh/v3 module as an example again, if I'm starting to consider what I would like to do with the API for a future v4, running the tool in its current mode can be a good way to spot if I want to drop any of the APIs I don't myself need, if I think they're no longer very useful to external users. And, on the other hand, some v0 modules are on the way to a v1, so they still try pretty hard to not break backwards compatibility.
The text was updated successfully, but these errors were encountered: