I'm really, really struggling to understand what the use-case is for the way that rust's current "unused fn/field/struct" warnings work.
Basically, these warnings all fall under the umbrella of rust's "dead code" warnings, which warn on all items that are not used by main
(in a binary) or any nameable pub
items (in a library). This means that a function that is called by other functions is still considered to be unused if all of the functions that call it are unused. (i.e. items can be "transitively unused")
Insofar as I can tell, this behavior has zero use cases. When dead code exists in a crate, there are two possible resolutions:
- It's not supposed to be dead, in which case you need to call it.
- It is supposed to be dead, in which case you need to delete it.
I find the current warnings to be a hindrance in both cases.
The current warnings hinder the integration of unused code
Suppose that the correct fix is to add a call to a function somewhere; maybe these functions were recently added and you never wrote their callsite. (for me, this is almost always the correct solution to these warnings). Which function do you need to call?
Unfortunately, the function you need to call is hidden amongst a tangle of warnings on other functions that are already called somewhere, making it difficult to find. This would be vastly easier if these "unused" warnings did not apply transitively.
The current warnings hinder the deletion of unused code
Suppose that the correct fix is to delete the unused functions (which is seldom the case for me). I used to think that the current dead_code
warnings would be helpful in this case. But in a recent attempt to minimize a crate for a bug, I found otherwise.
With an IDE
At some point while minimizing a crate for a bug report, I opened up a fairly important module to find 80% of it highlighted in yellow due to dead_code
warnings. Awesome, I thought! I can just select all of these things and delete them!
And so I selected the first contiguous region I could select, and deleted it. As I went to go select the next region, my IDE finished redoing its analysis, and all of the rest of the yellow highlights disappeared right before my eyes. The crate could no longer compile due to name resolution errors, so warnings were no longer highlighted. Oops!
With that, my only recourse was to find functions that contain errors, and delete them, one at a time. I did this for about 10 minutes. At some point, I finally stopped and git stashed everything, because I was worried that it might take me upwards of 40 minutes to get back to a state where I can build my code and verify that the bug is still present. I've been burned many times while minimizing code, and that was not a chance I was willing to take.
So what I ended up doing instead was to delete some things, wait for analysis to rerun, and hit Ctrl+Z if errors appear. This kept the crate in a valid state, so that I could always rebuild and run it to check for the bug. (if the compiler only warned on items that were directly unused, I would have been able to do the same thing without having to wait and potentially hit Ctrl+Z all the time)
Without an IDE
It felt absurd to me that I would have to delete things one-by-one when the compiler has already spit out warnings for all of the functions I need to delete.
So at some point I tried putting the cargo build
output on one monitor and the code in another, deleting unused functions in each file from the bottom up (so that the line numbers don't change). This felt awkward and was not much faster than my prior strategy of deleting functions that have errors. It still felt like it was going to take forever to get back to a state where I could compile the crate again, so I gave up.
The only way to make this viable would be if there were a tool to automatically delete all of the unused code in a single fell swoop. I recalled that rustfix
relies on warnings/errors provided by the compiler to implement its fixes, so I tried looking into its flags and settings to see if there was some way I could get rustfix to "fix" all of the dead_code
warnings. Unfortunately, I was unable to find anything.
Any counter-arguments?
So there you have it. I used to think that maybe the current behavior helped some people in some use cases, but after living through that scenario myself, I can only conclude that it is universally unhelpful.
Does anybody disagree with my experience? Who out there finds the current behavior genuinely useful?