Rust Abstractions
Rust is a fun language that advertises “zero cost abstractions”. In the Rust philosophy, abstraction is available, but hopefully with few performance tradeoffs. However, what Rust will not negotiate on is safety and correctness. It is fairly difficult to write certain types of unsafe code in Rust. The language intentionally makes it difficult.
C Abstractions
On the other end of the safety spectrum C advertises “well defined behavior”. You can ask for the compiler to generate a certain pattern of code and it will gladly comply. Whether your resulting code is useful or predictable is your problem and your fault.
Machine Code
Sometimes, even with all of these well-intentioned tools, it becomes necessary to inspect what the compiler is actually doing to your code. Debugging with a decompiler is sometimes helpful. Even making small edits to see what happens might be good. There are times when directly working with the machine is helpful.
The Machine is Honest
There is a certain type of “lie” that happens when a compiler transforms your code into machine code. The output is supposed to represent the input somehow, but the two programs are not exactly the same. The computer doesn’t work exactly as advertised by your favorite language. The abstraction comes at the cost of you, the programmer, learning specifically how the machine works.
Getting Familiar with your Toolset
In the end, compilers are tools. If you understand how the tool works, you will also learn to use it better. Nothing is worse than trying to use a hammer when you really need a mallet. Choosing languages is similar. Choose the right tool for the job.