Treating warnings as errors by default is bullshit

There is a new worrying trend about regarding warnings (Unused parameters, variables, unreachable code, etc) as errors, not only by default, but as the only option. Notably, Go and Zig does this very annoyingly and will not let you compile if there are any unused variables about. You would think that logically the compiler would simply drop these and be done with it, since there is no difference between keeping an unused variable or ignoring it (Unless in fact it is not unused). The only difference is that keeping around a variable that is written to would use up memory that an ignored one wouldn’t, but otherwise it would not affect the program. There are ideas thrown around by apologists, such as “anything worth warning about is worth stopping the build, and anything not worth stopping the build is not worth warning about”, or “the best solution is simply to remove the unused code”. Though I feel these people never work with actual code beyond textbook examples, because in a living environment things are never as black and white.

I have worked in projects where “make it work now and make it pretty later” is definitely a thing, and even projects where “make it pretty never” is also prevalent. This is fine - we are paid for the results of the program, the customer does not pay for the source code itself. In academic situations where the results of the program is not used, does not matter or is not the goal, I can understand the mantra of “blow up when a parameter is not used”, but that does not tend to be the salaried situation. This is why languages like Java and JavaScript are dominated in the jobs section and why people sitting in the basement ranting about side effects write Haskell code that is never run by anyone.

Compilers are tools, much like the text editor, the IDE, the versioning system, even the monitor and keyboard. It is meant to transform human readable text into machine executable code and warn the programmer when said text does not compute. The compiler does not tase the programmer over esoteric or aesthetic issues - this is the task of the linter, which is not mandatory. Whenever the compiler does this, the compiler developers are violating the Unix philosophy:

Write programs that do one thing and do it well.

Thanks, Ken Thompson. Compilers that break on small errors don’t do one thing, and they don’t do it well. Wait a minute, Thompson co-developed Go?

The practice promotes maintainable software?

Actually, I would argue that it does not. If you are going to refactor a large piece of code, which you probably will end up doing a lot if you are maintaining code, you will need to jump through hoops if you are incrementally ensuring that your refactoring does not break any existing functionality.

If your compiler is lenient about warnings, you will be able to:

If your compiler however is not lenient, you will have to:

I cannot fathom how any developer would seriously believe that the strict compiler will actually end up letting the programmer produce more maintainable code.

Any project where code correctness is important is going to be run with a linter anyway, and dirty fuzzy code will find a way to be hairy anyway, so there is zero benefit, and non-zero harm, with this practice.

Currently endorsed workarounds

In Go, you can use _ to give a dummy usage for unused variables:

func main() {
    var unused int
    unused = 42
    _ = unused
}

This marks our unused integer as used, so it will not incur the wrath of the compiler. Zig has a similar workaround. Since the compiler accepts this, it only really shows that the language authors realize on some level that you actually need this functionality in a programming language, but due to (ideological?) reasons it is hidden away in this manner, which interestingly enough would only mess up your codebase even more if there was an issue about unused code from the start. Zig even has a proposed feature to let the compiler insert these kind of statements automatically when it detects unused variables, which if you think about it for more than a couple of seconds you realize how horrible the idea of your compiler polluting your codebase is. Not to mention that it somehow is a problem but somehow isn’t, if this kind of workaround is permitted. You might as well just bring back warnings instead.

Stop the idea of breaking builds on unused imports and variables. This is objectively wrong and nonsense. Let compilers compile and let linters lint.


Comments