logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

Rust-is-not-a-good-C-replacement.md (7463B)


  1. ---
  2. date: 2019-03-25
  3. layout: post
  4. title: Rust is not a good C replacement
  5. tags: ["philosophy", "rust", "c"]
  6. ---
  7. I have a saying that summarizes my opinion of Rust compared to Go: "Go is the
  8. result of C programmers designing a new programming language, and Rust is the
  9. result of C++ programmers designing a new programming language". This isn't just
  10. a metaphor - Go was designed by plan9 alumni, an operating system written in C
  11. and the source of inspiration for many of Go's features, and Rust was designed
  12. by the folks at Mozilla - whose flagship product is one of the largest C++
  13. codebases in the world.
  14. The values of good C++ programmers are incompatible with the values of good C
  15. programmers[^1]. Rust is a decent C++ replacement if you have the same goals as
  16. C++, but if you don't, the design has very similar drawbacks. Both Rust and C++
  17. are what I like to call "kitchen sink" programming languages, with the obvious
  18. implication. These languages solve problems by adding more language features. A
  19. language like C solves problems by writing more C code.
  20. [^1]: Aside: the term "C/C++" infuriates me. They are completely different languages. Idiomatic C++ looks nothing like idiomatic C.
  21. I did some back of the napkin estimates of the rate at which these languages
  22. become more complex, based on the rate at which they add features per year. My
  23. approach wasn't very scientific, but I'm sure the point comes across.
  24. - **C: 0.73 new features per year**, measured by the number of bullet points in
  25. the C11 article on Wikipedia which summarizes the changes from C99, adjusted to
  26. account for the fact that C18 introduced no new features.
  27. - **Go: 2 new features per year**, measured by the number of new features listed
  28. on the Wikipedia summary of new Go versions.
  29. - **C++: 11.3 new features per year**, measured by the number of bullet points
  30. in the C++17 article which summarizes the changes from C++14.
  31. - **Rust: 15 new features per year**, measured by the number of headers in the
  32. release notes of major Rust versions over the past year, minus things like
  33. linters.
  34. This speaks volumes to the stability of these languages, but more importantly it
  35. speaks to their complexity. Over time it rapidly becomes difficult for one to
  36. keep an up-to-date mental map of Rust and how to solve your problems
  37. idiomatically. A Rust program written last year already looks outdated, whereas
  38. a C program written ten years ago has pretty good odds of being just fine.
  39. Systems programmers don't want shiny things - we just want things that work.
  40. That really cool feature $other_language has? Not interested. It'll be more
  41. trouble than it's worth.
  42. With the philosophical wish-wash out of the way and the tone set, let me go over
  43. some more specific problems when considering Rust as a C replacement.
  44. **C is the most portable programming language**. Rust actually has a pretty
  45. admirable selection of supported targets for a new language (thanks mostly to
  46. LLVM), but it pales in comparison to C, which runs on almost *everything*. A new
  47. CPU architecture or operating system can barely be considered to exist until it
  48. has a C compiler. And once it does, it unlocks access to a vast repository of
  49. software written in C. Many other programming languages, such as Ruby and
  50. Python, are implemented in C and you get those for free too.
  51. **C has a spec**. No spec means there's nothing keeping rustc honest. Any
  52. behavior it exhibits could change tomorrow. Some weird thing it does could be a
  53. feature *or* a bug. There's no way to know until your code breaks. That they
  54. can't slow down to pin down exactly what defines Rust is also indicative of an
  55. immature language.
  56. <iframe
  57. src="https://cmpwn.com/@sir/100437209244243864/embed"
  58. class="mastodon-embed"
  59. style="max-width: 100%; border: 0; margin: 0 auto; display: block;"
  60. width="400"></iframe>
  61. <script src="https://cmpwn.com/embed.js" async="async"></script>
  62. **C has many implementations**. C has many competing compilers. They all work
  63. together stressing out the spec, fishing out the loosely defined corners, and
  64. pinning down exactly what C is. Code that compiles in one and not another is
  65. indicative of a bug in one of them, which gives a nice extra layer of testing to
  66. each. By having many implementations, we force C to be well defined, and this is
  67. good for the language and its long-term stability. Rustc could stand to have
  68. some competition as well, maybe it would get faster![^2]
  69. [^2]: Rust does have one competing compiler, but without a spec it's hard to define its level of compatibility and correctness, and it's always playing catch-up.
  70. **C has a consistent & stable ABI**. The System-V ABI is supported on a wide
  71. variety of systems and has been mostly agreed upon by now. Rust, on the other
  72. hand, has no stable internal ABI. You have to compile and link everything all in
  73. one go on the same version of the Rust compiler. The only code which can
  74. interact with the rest of the ecosystem is unidiomatic Rust, written at some
  75. kind of checkpoint between Rust and the outside world. The outside world exists,
  76. it speaks System-V, and us systems programmers spend a lot of our time talking
  77. to it.
  78. **Cargo is mandatory**. On a similar line of thought, Rust's compiler flags are
  79. not stable. Attempts to integrate it with other build systems have been met with
  80. hostility from the Rust & Cargo teams. The outside world exists, and us systems
  81. programmers spend a lot of our time integrating things. Rust refuses to play
  82. along.
  83. **Concurrency is generally a bad thing.** Serial programs have X problems, and
  84. parallel programs have X<sup>Y</sup> problems, where Y is the amount of
  85. parallelism you introduce. Parallelism in C is a pain in the ass for sure, and
  86. this is one reason I find Go much more suitable to those cases. However, nearly
  87. all programs needn't be parallel. A program which uses poll effectively is going
  88. to be simpler, reasonably performant, and have orders of magnitude fewer bugs.
  89. "Fearless concurrency" allows you to fearlessly employ bad software design 9
  90. times out of 10.
  91. **Safety**. Yes, Rust is more safe. I don't really care. In light of all of
  92. these problems, I'll take my segfaults and buffer overflows. I especially refuse
  93. to "rewrite it in Rust" - because no matter what, rewriting an entire program
  94. from scratch is *always* going to introduce more bugs than maintaining the C
  95. program ever would. I don't care what language you rewrite it in.
  96. ---
  97. C is far from the perfect language - it has many flaws. However, its
  98. replacement will be simpler - not more complex. Consider Go, which has had a lot
  99. of success in supplanting C for many problems. It does this by specializing on
  100. certain classes of programs and addressing them with the simplest solution
  101. possible. It hasn't completely replaced C, but it has made a substantial dent in
  102. its problem space - more than I can really say for Rust (which has made similar
  103. strides for C++, but definitely not for C).
  104. The kitchen sink approach doesn't work. Rust will eventually fail to the "jack
  105. of all trades, master of none" problem that C++ has. Wise languages designers
  106. start small and stay small. Wise systems programmers extend this philosophy to
  107. designing entire systems, and Rust is probably not going to be invited. I
  108. understand that many people, particularly those already enamored with Rust,
  109. won't agree with much of this article. But now you know why we are still writing
  110. C, and hopefully you'll stop bloody bothering us about it.