Every project and programmer shouldn't feel they have to justify their choice not to use Rust (or Zig), who seem to be strangely and disproportionately pushed on Hacker News and specific other social media platforms. This includes the pressure, though a bit less in recent years, to use OOP.
If they are getting good results with C and without OOP, and people like the product, then those from outside the project shouldn't really have any say on it. It's their project.
I am a pretty serious "Rustacean", but I like to think "for the right reasons". A rewrite in Rust of the main project would make very little sense, unless there is some objective the project wants that can't be met with C (see below). This person presents a well thought out case on why it makes little sense to rewrite, especially in the final section. Rust is great for many things, but when you have something old that is already so well tested and accessible on all sorts of obscure platforms, it makes little sense to rewrite, and the likely result would be more bugs, not less, at least in the short term.
All that said, some have found reasons to rewrite in Rust, and are currently working on that: https://turso.tech/blog/introducing-limbo-a-complete-rewrite...
This seems like the way. Why would Rustaceans bother to "argue their case" before an unwilling board if they can just do the rewrite themselves? Maybe it will succeed, maybe not, but you don't need SQLLite's blessing to test the proposition.
I agree. We will see how Limbo turns out :)
I forgot what Limbo was, Rust rewrite of SQLite, now called Turso.
https://github.com/tursodatabase/turso
I could see it being useful for pure Rust projects once its completed. I mean in Java / Kotlin land, I prefer to use H2 in some cases over SQLite since its native to the platform and H2 is kind of nice altogether. I could see myself only using this in Rust in place of SQLite if its easy to integrate and use on the fly.
The equivalent "platform native" database for Clojure is Datalevin [0], which has a Datomic-like Datalog query language with SQLite-style semantics. Recommended.
Honestly, instead of porting SQLite to Rust, IMO, it makes more sense to make an easier-to-use embedded database (in Rust) first.
Is SQLite hard to use?
The final comments in this text seem sobering and indicate an openness to change. I worked recently on a project to migrate RediSearch to Rust, and this was partially motivated by a decent number of recent CVEs. If SQLite doesn't have this problem, then there needs to be some other strong argument for moving to Rust.
I also think it's important to have really solid understandings (which can take a few decades I imagine) to understand the bounds of what Rust is good at. For example, I personally think it's unclear how good Rust can be for GUI applications.
It's nice that they don't dismiss out-of-hand the idea of using a language other than C (the conclusion is far less dogmatic than the editorialized title here suggests (the actual title of the page being "Why Is SQLite Coded In C?")). But let's be clear that the stability and "boringness" that C currently enjoys took literal decades to realize (pre-ANSI C was a wild-west shitshow that makes pre-ECMA Javascript look tame by comparison), and giving the same leeway to other languages probably doesn't suggest using e.g. Rust until at least 2040 or so.
Something like Ada/SPARK might be a better choice for something like SQLite as well.
> But no other language claims to be faster than C for general-purpose programming, because none are.
The "faster than C for general-purpose programming" is a pretty woolly claim so I'm not entirely surprised nobody claims that, but equally I think to be sure that "because none are" would need some serious caveats to make it true.
In particular you're going to have to say you think it doesn't matter how much developer time is needed. A project where C programmers spend five hours to make it run in 4 seconds is in this caveat "20% faster" than a project where Alt Lang programmers spend five minutes to make it run in 5 seconds - because only those seconds count. This is not how the real world works so it's a pretty nasty caveat.
> Rust needs a mechanism to recover gracefully from OOM errors.
Linus also brought this up: https://lkml.org/lkml/2021/4/14/1099
None of Rust's language features allocate; not arrays, not closures, not iterators. Everything is stack-allocated by default. Rust code doesn't malloc unless you use a library that calls malloc; in other words, exactly like C. Rust fully supports turning off the parts of the standard library that perform allocation, and this is precisely what embedded code and the Linux kernel does. So Rust already gives you full control.
well, as an example, Vec::push doesn't have a way to report allocation failure. it will just panic, which is not acceptable in the kernel.
Sure, which is a perfectly acceptable default considering that most code is not in a position to observe allocation failures (because of OS-level overcommit, which is nearly always a good thing), and furthermore most code is not in a position to do anything other than crash in an OOM scenario. If you still want to have control over this without going full no_std, Rust has Vec::try_reserve to grow a Vec while checking for allocation errors, as well as several nightly functions coming down the pipe in the same vein (e.g. Vec::try_with_capacity, Vec::push_within_capacity).
>does not mean that the system is out of memory. >"The allocator could have "ulimit" or such limit that is completely independent from actual process/system limitations."
Are we playing word games here? If a process has a set amount of memory, and it's out of it, then that process is OOM, if a VM is out of memory, it's OOM. Yes, OOM is typically used for OS OOM, and Linus is talking about rust in the kernel, so that's what OOM would mean.
>Secondarily what reason is there to make an allocation failure any different than any other resource allocation failure.
Of course there is, would you treat being out of bread similar to being out of oxygen? Again this can be explained by the context being kernel development and not application development.
Handling OOM gracefully - i.e. doing anything other than immediately crashing and/or invoking undefined behaviour - is absolutely not the default in C.
It's possible. But very very few projects do.
> That's intentional; IOW the "most code" that is unable to handle OOM conditions are written that way.
No, this is wishful thinking. While plenty of programs out the are in the business of maintaining caches that could be optimistically evicted in order to proceed in low-memory situations, the vast majority of programs are not caching anything. If they're out of memory, they just can't proceed.
I used to think this way many years ago, then I saw my own code in production hit OOM errors and manage to recover, and even log what was happening so I could read about it later.
After those experiences I agree with the sibling comment that calls your position "bullshit". I think people come to your conclusion when they haven't experienced a system that can handle it, so they're biased to think it's impossible to do. Since being able to handle it is not the default in so many languages and one very prominent OS, fewer people understand it is possible.
Now you need to ensure that your entire error path does not allocate or you have to deal with allocation errors in the error path as well.
Trying to apply backpressure from memory allocation failures which can appear anywhere completely disconnected from their source rather than capping the current in memory set seems like an incredibly hard path to make work reliably.
That's why you don't use std in this case. You limit yourself to things defined in core.
That seems like an enormous question. Is anyone working on it?
And of course the kernel - which doesn't even use Rust's Vec but has its own entire allocator library because it is the kernel - likewise provides
https://rust.docs.kernel.org/next/kernel/alloc/kvec/struct.V...
Vec::push_within_capacity is a nice API to confront the reality of running out of memory. "Clever" ideas that don't actually work are obviously ineffective once we see this API. We need to do something with this T, we can't just say "Somebody else should ensure I have room to store it" because it's too late now. Here's your T back, there was no more space.
Yeah, it's not ideal that the standard library currently has blind spots around allocation and I hope those get resolved eventually, but if you're rolling everything from scratch in C anyway then it's not much of a stretch to likewise roll your own Rust primitives in places where the included batteries don't work for you.
you understand that stack allocation can OOM too?
Can C gracefully recover from running out of stack space?
Yep, the “split” between core and std is brilliant. It enables so many usecases: one example I ran into recently is compiling Rust (core) to eBPF.
Great to know!
Off topic: This CSS improves the usability of that page:
ul.threadlist li:hover > a {
color: red;
}
ul.threadlist li.origin > a {
display: block;
background: rgb(205, 216, 216);
font-weight: normal;
padding: 1px 6px;
margin: 1px -6px;
}He's not wrong, but needs to clean own house a bit.
> Rust needs to mature a little more, stop changing so fast, and move further toward being old and boring.
One of the very strange things about C is that it is designed by a committee that is inherently conservative and prefers to not add new features, especially if they have any chance of breaking any compatibility. This seems necessary before Rust ever becomes an old, boring language.
But I don't see Rust ever going in such a direction. It seems fundamentally opposed to Rust's philosophy, which is to find the best solution to the problems it's trying to solve, at any cost, including breaking compatibility, at least to some degree.
The 'some degree' is pretty important, though. The Rust language undergoes backwards incompatible changes sometimes, but the Rust tools do not. The 2024 edition has breaking changes since the 2021 edition, but all compilers can compile all historical editions and will do so forever, and new language features are available in as many editions as possible, and editions can be mixed in a dependency tree, so you do not ever have to update your 2015 edition code for anything.
Sounds like textbook bc break. I'm curious as to what you think a bc break would look like?
Consider python2 and python3, you don't need to update your python2 code really, you can just use the python2 interpreter.
No you’re misunderstanding the ecosystem. Rust 2024 code can call 2021 code without issue (and vice versa I think although could be wrong on the vice versa). So you can progressively update code of individual components as you want or not at all and still continue using it just fine in new code using later editions. Thats the very definition of back compat, something you really really shouldn’t do with C++ (every file should be compiled with the same language version target although practically that may be less of an issue depending on the specific stdlib implementation and if they break ABI)
There’s also automated migration tools to convert 2021 code to 2024. It might fail on some translations but generally it’s pretty automatic.
So huge difference both in the migration mechanism and the bc story.
The equivalent in python-metaphor-land would be that python files clearly designate whether they are py2 or py3, and a single python interpreter can run both py2 and py3 scripts, as well as cross-include files of each version without issue.
Rust editions only (and rarely!) break your code when you decide to upgrade your project's edition. Your public API stays the same as well (IIRC), so upgrading edition doesn't break your dependents either -unless they don't have a new enough version of the compiler to support said newer edition.
> Rust's philosophy, which is to find the best solution to the problems it's trying to solve, at any cost, including breaking compatibility, at least to some degree.
But the Rust team found a great way to avoid breaking backward compatibility: old code gets automatically compiled by the old version of the compiler, whereas more recent code is treated with the latest version of the compiler.
That is much better IMHO than carrying that old baggage along in the language that e.g. the C++ folks struggle with, where every half-decade a pile of additive changes get piled on the previous version of the language, and nobody can clean up the old mess.
> old code gets automatically compiled by the old version of the compile
That's not what happens. You always use the same version of the compiler. It's just that the newer compiler version also knows several older dialects (known as editions) of the language.
And it remains to be seen how well this approach will work as time passes and the number of versions continues to increase.
Well, there's the 2015, 2018, 2021, and 2024 editions. It's been a decade and it seems to be working pretty well?
This may have its own landmines. Worst case, old code getting compiled in the old way could mean that the exact same line means different things depending on which file it's in. (I don't know whether it is possible with how Rust does this.)
Sure, Rust can compile old code. But you can't upgrade that old Rust code to new Rust code very easily.
The fact that C was effectively "born old" means you can take a C89 program and compile it as C23 and it should simply work, with extremely minimal changes, if any.
That's a killer feature when you're thinking in decades. Which SQLite is.
You would need to be incredibly careful with compiling old C89 code on a modern compiler. It's not the language changes that would get you, it's a change in how compilers treat undefined behavior.
There has always been undefined behavior in C, but back in the day, compilers were nowhere near as aggressive in taking advantage of it to make your code faster. Most C programmers tended to treat C as portable assembly and not a language with rules that needed to be respected for it to not blow up your code.
I remember this being endlessly groused over by grognard, traditionalist C programmera, and more than a few of them switched to C++ as a result. After all, if the language was going to be a stickler about correctness, they might as well use a language with the features that meant they didn't have to reach into that bag of tricks.
> There has always been undefined behavior in C, but back in the day, compilers were nowhere near as aggressive in taking advantage of it to make your code faster.
That much is true. If you put the derefence of a pointer and the null check in the wrong order both those statements would have code emitted for them.
Now, it is almost certain that one of those statements would not be emitted.
OTOH, compiling with -O0 still leaves most code to be emitted and fewer dead-code elimination places.
I truly believe that the cult of c performance optimization has done more harm than good. It is truly evil to try and infer, or even worse, silently override programmer intent. Many if not most of the optimizations done by llvm and gcc should be warnings, not optimizations (dead code elimination outside of LTO being a perfect example).
How much wasted work has been created by compiler authors deciding that they know better than the original software authors and silently break working code, but only in release mode? Even worse, -O0 performance is so bad that developers feel obligated to compile with -O2 or more. I will bet dollars to donuts that the vast majority of the material wins of -O2 in most real world use cases is primarily due to better register allocation and good selective inlining, not all the crazy transformations and eliminations that subtly break your code and rely on UB. Yeah, I'm sure they have some microbenchmarks that justify those code breaking "optimizations" but in practice I'll bet those optimizations rarely account for more than 5% of the total runtime of the code. But everyone pays the cost of horrifically slow build times as well as nearly unbounded developer time loss debugging the code the compiler broke.
Of course, part of the problem is developers hating being told they're wrong and complaining about nanny compilers. In this sense, compiler authors have historically been somewhat similar to sycophantic llms. Rather than tell the programmer that their code is wrong, they will do everything they can to coddle the programmer while behind the scenes executing their own agenda and likely getting things wrong all because they were afraid to honestly tell the programmer there was a problem with their instructions.
My company maintains a medium set of Rust programs deployed on embedded Linux systems. Most of the time the migration is automatically done for you by Cargo itself with the command `cargo fix --edition`.
I don't know where you got this impression but our switches from 2018 to 2021 and now 2024 editions went very smootly. Rust hasn't broken backwards compatibility in any bigger way since 1.0.
When clang was first coming about, the number one cause of Debian packages failing to build with clang was that (at the time) clang defaulted to C99 whereas gcc defaulted to C89.
True that!
No not true. cargo fix —edition automatically does most translation to the new edition (most people never see it fail, I’ve seen it fail only on some obscure constructs that it couldn’t do automatically because the meaning of some trait stuff changed subtly but took 2 minutes or less to fix). cargo clippy —-fix will automatically apply linter fixes or warning fixes when it can.
Claiming that editions are an example of rust failing back compat shows a complete ignorance of the ecosystem or what coding in the language is actually like. People in this thread think you can’t mix n match editions or that migrating is some huge unavoidable obstacle. Indeed I have less fear upgrading editions than I do bumping the version of the c or c++ language or even using a newer compiler that exploits accidental UB that had been lurking.
The great thing about C is that is was not designed by a committee at all. It was designed by a person with strong opinions. This means it is really great for what it does well(what the author was interested in).
To illustrate the difference look at C++, it was designed by a person with strong opinions, but then left it to be controlled by a committee.
If you look at the structure of C++ in Backus Naur form it is absolutely nuts. The compile times have gone through the roof and people leave to create new languages like jai, Zig or whatever.
Common Lisp was designed by committee. It is as chaotic as C++.
Rust is also gigantic. I am very careful not to use in critical systems because it is so big unless we could restrict it with the compiler or something.
For what it’s worth rust was also designed by a person with strong opinions. It’s devolved to an organization but that’s inevitable in terms of long term sustainability.
You can always use no-std if you so choose where the language is about the size of C (but still has better utility) although if you’re complaining about the size of the language, c++ is drastically worse in my opinion. Rust starting to work its way into the Linux kernel should be a signal that the language is better suited for paring down than c++
Calling C "strange" for being conservative and not wanting to break things is rather odd. It's one of the "great" things in that sense. "Stable" could be another description.
Depends on what it’s unwilling to break. “The compiler generates code that segfaults when you multiply 13 * 37, but someone found a way way to trap it and used that as a faster way to make syscalls on Prime minicomputer, so we had to add -ffix-four-eight-won, which the original implementor misspelled in 1993 so we can’t fix that, either, for backward compatibility.”
Some of its actual weirdnesses seem no less odd than that to people who aren’t C experts, I assure you.
Uh oh! I think Rust may settle down eventually. Who knows, maybe one of the devs will chime in.
Oh look. Something works. Lets not break it? How crazy is that?
I sometimes wonder if what happens is like this:
1. Have problem. Need higher level computer language. 2. Think about problem. 3. Solve problem - 'C' 4. Think about problems with 'C' 5. Attempt to fix problems with 'C' - get C++ 6. Think about problems with C & C++ 7. Get: Go, F#, Rust, Java, JavaScript, Python, PHP, ...other etc.
I tend to do this. The problem is obvious, that I do not repeat step #2. So then I move to the next step.
8. Thinking about how to fix C, C++, Go, F#, Rust, Java, JavaScript, Python, PHP, ...other is too hard. 9. Stop thinking.
Although Mozilla's reason to pay for Rust R&D was because of problems with C++ it's probably not most helpful to think of Rust (let alone F#) as an attempt to specifically fix those problems.
C is a Worse is Better language (https://en.wikipedia.org/wiki/Worse_is_better). The bet is that if it's simpler to implement then the fact that what you're implementing isn't great will be dwarfed by that ease of implementation. And it worked for decades which is definitely a success.
You can make a similar argument for Go, but not really for Rust. The other side of the Worse is Better coin is that maybe you could make the Right Thing™ instead.
Because implementing C is so easy and implementing the Right Thing™ is very difficult, the only way this would compete is if almost nobody needs to implement the Right Thing™ themselves. In 1970 that's crazy, each Computer is fairly custom. But by 1995 it feels a lot less "out there", the Intel x86 ISA is everywhere, Tim's crap hypermedia experiment is really taking off. And when Rust 1.0 shipped in 2015 most people were able to use it without doing any implementation work, and the Right Thing™ is just better so why not?
Now, for an existing successful project the calculation is very different, though note that Fish is an example of this working in terms of full throated RIIR. But in terms of whether you should use C for new work it comes out pretty strongly against C in my opinion as a fairly expert C programmer who hasn't written any C for years because Rust is better.
The problem with articles like this is that they read a little like justifying a decision that has already been made. I've a feeling that if it was written in C++/Rust/Go/whatever, it would also be possible to justify that decision with similar reasoning.
No it's not. Arch is the best. https://wiki.archlinux.org/title/Arch_is_the_best
As an outsider when I read about Rust it seems like it is positioning itself as the language to rewrite things that already work.
It's just the simplistic first feeling of a language, in the same way I feel like Go is the language for Kubernetes/cloud/net servers, Ruby is for Rails, JS is the browser/bootcamp language, Python is Data Science and AI...
Sure, you get that safety but you are also throwing the stability that an old (and maintained) codebase has just for the sake of being patched to handle the presssure from the real world.
Maybe it's time Rust positions itself as something more than "the language of rewrites".
who is this that you are claiming is "positioning" itself??? the Rust maintainers? No. Programmers are choosing to write something in Rust and it just so happens they are interested in rewriting something that already exists because they can. You write as if Rust is an entity that chose to position itself. What is your argument here? Rust should just go do something else? You wouldn't dare say that about Python. Also, how dare you put these languages in a corner. I've use ruby for many things other than Rails. JS is much more than a browser language now, and python is much more than data science and AI. Go is much more than Kubernetes/cloud/net servers.
> Nearly all systems have the ability to call libraries written in C. This is not true of other implementation languages.
This is no longer true. Rust, Zig and likely others satisfy this requirements.
> Safe languages usually want to abort if they encounter an out-of-memory (OOM) situation. SQLite is designed to recover gracefully from an OOM. It is unclear how this could be accomplished in the current crop of safe languages.
This is a major annoyance in the rust stdlib. Too many interfaces can panic (and not just in case of an OOM), and some of them don’t even document this.
> This is no longer true. Rust, Zig and likely others satisfy this requirements.
Rust and Zig satisfy this by being C ABI-compatible when explicitly requested. I'm pretty sure that that solution is not actually what the author meant. When you don't explicitly use `extern "C"` in Rust or `export` in Zig, the ABI is completely undefined and undocumented. I would go as far as arguing that the ABI problem, with Rust at least, is even worse than the ABI problem C++ has. Especially since Distros are (if memory serves) starting to ship Rust crates...
I agree that C is best. I think Rust is actually a language with some severe downsides, despite having including some very good ideas and C having some real issues. But it will take a couple of years before one can discuss this rationally without being flamed at.
If you want to spread this idea, it would probably help your cause if you pointed to what you think Rust does particularly poorly. Steep learning curve, npm-esque packaging?
The article gave many good reasons where Rust is lacking. The points you raise are also clearly issues. My main additional issues are the high complexity, the syntax, the lack of stability, compilation times (and monomorphization), and lack of alternate implementations. Ignoring the language itself, the aggressive and partially misleading negative and positive marketing.
> Rust is actually a horrible language
Can you expand a little?
They never said it's a horrible language.
The original comment was edited after I replied.
Yes, sorry, apparently not quick enough. I actually do not think it is horrible. It is a nice language, but I still do not like it and see many downsides. What I hate though is how aggressively it is marketed. See my other response for details.
I'm a little surprised they're at all open to a rewrite in Rust:
> All that said, it is possible that SQLite might one day be recoded in Rust.
...followed by a list of reasons why they won't do it now. I think the first one ("Rust needs to mature a little more, stop changing so fast, and move further toward being old and boring.") is no longer valid (particularly for software that doesn't need async), but the other ones probably still are.
I write Rust code and prefer to minimize non-Rust dependencies, but SQLite is the non-Rust dependency I mind the least for two reasons:
* It's so fast and easy to compile: just use the `rusqlite` crate with feature `bundled`. It builds the SQLite "amalgamation" (its entire code basically concatenated into a single .c file). No need to have bazel or cmake or whatever installed, no weird library dependency chains, etc.
* It's so well-tested that the unsafety of the language doesn't bother me that much. 100% machine branch coverage is amazing.
From what they have written, the only other language that meets their requirement seems to be Ada:
1. Stability: Ada is an "old and boring" language (aka stable and reliable - the first standard for the language was issued in 1983 and created for the Defence industry) - https://learn.adacore.com/courses/intro-to-ada/chapters/intr...
2. Compatibility: Interoperability features is built-in, allowing you to create Ada libraries that can be used with other languages - https://piembsystech.com/interfacing-ada-programming-with-c-...
3. Embedded Programming: Ada has been designed for embedded programming and the language includes constructs for directly manipulating hardware, for example, and direct interaction with assembly language. - https://learn.adacore.com/courses/intro-to-embedded-sys-prog...
4. Ada supports processes / suites to comply with Branch coverage in ISO 26262 ( https://github.com/NVIDIA/spark-process ) and Decision coverage in DO-178C ( https://learn.adacore.com/booklets/adacore-technologies-for-... ).
5. Ada has features supporting memory safety to avoid many memory issues in the first place ( https://www.adacore.com/blog/memory-safety-in-ada-and-spark-... ) but using its exception handling and programming techniques (like pre-allocating "guard" memory) can allow Ada programs to tackle fringe OOM errors.
6. Performance: Ada is built for systems programming, is just as fast as C ( https://learn.adacore.com/courses/Ada_For_The_Embedded_C_Dev... ), with the added bonus of "modern" programming features that can generate more "reliable" code
Well, can't argue with it. Ruby and Python are written mostly in C underneath.
Many try to replace C. All failed.
I'd love to see a language that could satisfy both high end needs and low need needs. I would not know how such a language would look though.
2017 at least[1] but "This page was last updated on 2025-05-09 15:56:17Z."
[1] https://web.archive.org/web/20170701061906/https://sqlite.or...
I'd like to see Steve Yegge unleash his Gas Town with a convoy or whatever it's called to rewrite the sqlite in Rust obviously preserving 100% test coverage. Results are a guaranteed bombshell regardless of whether it succeeds or fails.
What’s Steve Yegge got to do with Rust? And who’s gonna sponsor some 10,000 hours to “rewrite the sqlite in Rust obviously preserving 100% test coverage”? Will he do it just for the memes, or did you think Rust is so cool there is no effort involved?
Let’s be serious now.
What's not serious? He's got a tool which he claims should be able to handle projects of this scale, the existing test coverage is what makes it not immediately impossible and about the memes, have you read his gas town post? Of course it's for the memes, but more importantly it'll validate his vision of the future in the eyes of quite literally everyone if successful.
I’m sure it’ll be updated more
Given SQLite's amazing battery of test code, it seems like it would be valuable, illuminating, and not too difficult to write a test implementation in Rust. Can you get the Rust implementation to pass the test suite? Either answer to that question would be interesting.
SQLite's test suite is proprietary.
A Rust implementation exists. It's called turso
https://github.com/tursodatabase/turso
There's a whole company around it.
"In a more complete build, SQLite also uses library routines like malloc() and free() and operating system interfaces for opening, reading, writing, and closing files."
Whoa. TIL there's a minimal build of SQLite that doesn't even need malloc() and free() !
Presumably for embedded devices. I'd love to see examples of that being used in the wild.
Actual title: Why Is SQLite Coded In C
> Safe languages usually want to abort if they encounter an out-of-memory (OOM) situation. SQLite is designed to recover gracefully from an OOM.
As someone who runs into this problem a lot, this is pretty cool! Does anyone know how they can recover from this in SQLite?
> As someone who runs into this problem [OOM]a lot, this is pretty cool! Does anyone know how they can recover from this in SQLite?
How are you running into it?
If you're writing in C, idiomatic code works (check the return values of functions that allocate!)
If you're in C++, Rust or similar, you have to write pretty non-idiomatically to recover from an allocation failure.
how exactly do you think C and C++ differ here?
> how exactly do you think C and C++ differ here?
`new` throws, `malloc` returns. That's a pretty big difference!
Idiomatic C++ code never puts a `try` around `new`, while idiomatic C code always checks the return from an allocation.
An oom is when malloc failed
So you have to ensure that in such situation, you can execute code that does not require more memory: ensure that the rest only free stuff, or preallocate structures for that purpose
Well they don’t have to wait for Rust in the way they said - they’ve already been forked by Turso which has been moving along for a while now. I wouldn’t mind hearing from them how that’s been going.
Many non-programmers think that programming languages get outdated, just like operating systems or computer hardware, or even some software (old algorithms replaced by better algorithms), and each programmer should "follow trends", since using the same programming language for 10+ years sounds wrong.
But programming languages are like Math. It is like saying "multiplying is outdated" or "the square root is outdated".
if you don't think programming languages can get outdated then why is assembly, fortran, lisp, smalltalk, pascal, basic practically disappeared? programming languages are not like math, it's like the moon
> Libraries written in C++ or Java can generally only be used by applications written in the same language. It is difficult to get an application written in Haskell or Java to invoke a library written in C++. On the other hand, libraries written in C are callable from any programming language.
Not saying they should have picked C++ but that's a bit untrue. It's quite easy given some thought into the API to invoke C++ code in basically any language which can invoke C code, since you can wrap a C++ implementation in a C interface. I've done it multiple time throughout my career (that ended up being called from Python, Swift, Objective-C/C++, Swift, Java, and Kotlin).
And as a side note, you don't have to do object-oriented programming in C++ if you don't want to.
Yeah, it's not a very convincing argument imho. You can write C libraries in C++ or Rust or D or Zig, and people do it all the time.
In fact, some popular C++ libraries don't even have a stable C++ API, only a C API. LLVM comes to mind. DuckDB is another example
> It's quite easy given some thought into the API to invoke C++ code in basically any language which can invoke C code, since you can wrap a C++ implementation in a C interface
Is it easy to write a nice C interface for C++ that makes heavy use of templates, smart pointers, and move semantics?
I've only seen it done for C++ that is more C than C++, or for libraries that were designed to "bail out" to a C interface.
> Is it easy to write a nice C interface for C++ that makes heavy use of templates, smart pointers, and move semantics?
If the interface itself has or leaks those features, no that's not easy indeed. But if those do not leak, then they can be used internally yes.
My point was not that it's easy to wrap a currently existing C++ library that has modern features in its interface in a C interface, especially post-C++11.
But that if you design something from the ground up, then it's rather easy (with a certain set of constraints). My bad for not conveying that better.
That's definitely true. Can't have generics / compile time evaluation across languages. Need to design your code around that restriction ahead of time. SQLite being dynamically typed luckily doesn't have any problems with that.
I've actually run into a similar problem with a C library before, because it heavily used macros as part of its API. Glad most developers don't do that.
You lose most of the advantages of C++ if you can't use vector, unique_ptr and the like in your APIs. Classes are also useful for a lot of things.
You do lose the ability to use some features, that's true. Mostly RAII around the interface. You can still leverage it internally in the implementation, and if using context objects it would be even easier. The main pain point is if you want to let client of the library use their own allocators. It's still doable, but quite a pain.
Classes can be wrapped with a bit of effort. You do need to write the constructors and the destructors manually and invoke a pair of new/delete on the C side, but it's just as you would handle a type allocated by a C library itself. You'd use it the same way. You just have the liberty to have the implementation use (mostly) C++.
You can still use them inside your code, just not as arguments or return values from the API.
And it's not like that's a point in favor of C, since C doesn't have vector or unique_ptr either
BTW, the study referred to in 1.2, which claims that SQLite was faster than the file system is not supported by the numbers in the study referenced:
> For a my real(ish) world scenario, SQLite-- once warmed up-- is roughly twice as fast as the file system.
is that actually surprising ?
once data leaves the fs and is all (or in part) bought into a processes memory, access is just limited by the memory bandwidth.
ofcourse if you start touching uncached data things slow down, but just for a short while…
previous discussion a few months ago: https://news.ycombinator.com/item?id=45584464
I believe this article is from a few years ago
Updated quite often I see.
The bit about why not OOP seems a bit old. I think we're past a point where people are going for OOP as the default shape of code.
Overall, it makes sense. C is a systems language, and a DB is a system abstraction. You shouldn't need to build a deep hierarchy of abstractions on top of C, just stick with the lego blocks you have.
If the project had started in 2016, maybe they would have gone for c++, which is a different beast from what it was pre-2011.
Similarly, you might write SQLite in Rust if you started today.
> The bit about why not OOP seems a bit old. I think we're past a point where people are going for OOP as the default shape of code.
That section was probably written 20 years ago when Java was all the rage.
I think they would have still gone with C. I still do.
The author of ZMQ had an article about regretting not using C over C++. Picking Rust for a "modern" version of SQLite could easily go down a similar route in the end.
https://web.archive.org/web/20250130053844/https://250bpm.co...
Makes a lot of sense for SQLite to be written in C. It's a heavily optimized and debugged database implementation: Just look at btree.c with all its gotos :)
The only language that would make sense for a partial/progressive migration is zig, in huge part due to its compatibility with C. It's not mentioned in the article though.
Zig hasn't even had it's first release yet. And projects written in it still break in new releases. Given their stance on boringness and maturity it would make no sense for Sqlite to consider zig yet.
SQLite is never gonna be rewritten by its creators in another language. That is highly doubtful considering the age of SQLite and the roadmap for support I think until 2060 or mid 2050s based on what I’ve read.
> SQLite is never gonna be rewritten by its creators in another language.
Almost certainly correct. It is however being rewritten in Rust by other people https://github.com/tursodatabase/turso. This is probably best thought of as a seperate, compatible project rather than a true rewrite.
For better or worse, plenty of serious projects are using Discord for communication. It's not great, but IRC and Matrix have their own problems (IMO Zulip is the best of the bunch, but doesn't seem to be particularly widely adopted).
You're right. Just look at their branding. Such poor taste. I'm sure it's a scam.
The amount of completely obscure and exotic platforms that have C compiler, and the amount of tooling and analysis tools C has — I'd be surprised anything comparable exists.
What would be a reason to bring Zig in?
For example, Rust has additional memory guarantees when compared to C.
Maybe DRH will see this and update the page !
*C-API is the best.
As a language, it's too basic. Almost every C projects try to mimic what C++ already has.
I considered it outdated back in 1993, when all major GUI based systems (Apple, IBM, Microsoft) were going with C++ for userspace applications.
Then came the rise of FOSS adoption, with the GNU manifest asserting to use only C as compiled language.
"Using a language other than C is like using a non-standard feature: it will cause trouble for users. Even if GCC supports the other language, users may find it inconvenient to have to install the compiler for that other language in order to build your program. So please write in C."
The GNU Coding Standard in 1994, http://web.mit.edu/gnu/doc/html/standards_7.html#SEC12
Ah, C has stable ABI unlike C++, never would get tired of unresolved std::__1 symbols.
That’s not true, give me an example used in real code out in the wild?
Since I am feeling generous, here are two examples,
Thank you
For big, fixed environments like Qt — sure. For embedded? Please no. Basic is good. Feel free to reimplement C++, your C library still will not have: most of STL as a dependency; unwind tables in all code (including C!); ctor/dtor arrays; insane kilobyte-sized symbols.
i haven't seen any rust projects yet that maximize embeddability, portability, space and transparency. maybe an argument could be made for the linux kernel stuff, but nothing like a sqlite that gets compiled and included in a million things on a million platforms ranging from high level interpreter wrappers on general purpose computers to teeny microcontrollers where the operating system is a library or some jump targets in rom.
that said, just because c is best for sqlite today, doesn't mean c is best for you or what you're trying to do.
I can't imagine how writing C directly could possibly be better than using a language like Dafny and then generating C code.
Edit: Dafny: A verification language capable of enforcing invariants
The title is "Why Is SQLite Coded In C", not "C Is Best". The content is far more nuanced than this specific section title suggests.
C is fast and maybe has predictable performance, but, for example, strcmp(), strlen(), strncmp() are not as fast (and also secure) as C++ std::string analogs, unless you don't help a bit by storing the string lengths.
The actual title is "Why Is SQLite Coded In C"
Ada is best.
No UB, strict types, contracts that can be formally proven, runtime checks, better (than phthreds) concurrency, certifiable.
It's bitch sometimes but you'll thank it after release.
This submission title has been editorialized, contrary to the HN guidelines. The article title is actually "Why Is SQLite Coded In C".
Also, the article appears to be quite old, so the submission should have a year appended.
See also previous discussions, the last of which was only a few months ago: https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
Given they added Section 2 and 3 in response to previous commentary: https://news.ycombinator.com/item?id=16585120
it seems rather stupid to take a sub-heading as the title.
C is good
Yup. But, they're all good in their own way. They're just a means to an end. If the end result is good, reliable, maintainable: whatever you use is good.
I long to see an sq-rust project!
Tittle should be "C is a Standard"
Title should actually be “Why Is SQLite Coded In C”, since that’s the title of the article.
no, triples is best!
What does “Go hates assert()” mean?
...at what it does, couldn't agree more.
DRH writing truth! People love to jump to Rust or C++.
What the post says is that you can do software engineering in C and be portable.
I love C and Assembly and I'm impressed by the things people can build in those languages and often (not always) I can understand the code written in it. It's also true that code written in it is available to every other language. For that I'm very happy, as I'm mostly working in higher level languages that can call things like sqlite.
Just imagine if all of Chromium was written in C and used simpler tools like GNU Make and Git for it's projects.
There's already attempted re-implementations of SQLite in Rust, so if it really is a good approach, time should tell.
https://turso.tech/blog/introducing-limbo-a-complete-rewrite...
Really time will tell indeed. It’s too early.
When the Rust version has the same take-up as the C version I know and trust, I might use it. Until then I'll wait. What's available now is good. I'm in no hurry to use an alternative. I like the idea of a reliable black-box, and I don't overly care how the black-box does its magic.
This makes sense with the quality and quantity of testing they do.
https://sqlite.org/testing.html
>As of version 3.42.0 (2023-05-16), the SQLite library consists of approximately 155.8 KSLOC of C code. (KSLOC means thousands of "Source Lines Of Code" or, in other words, lines of code excluding blank lines and comments.) By comparison, the project has 590 times as much test code and test scripts - 92053.1 KSLOC.
Absolutely.
.. one of the safe languages like.. Go.. o_O
Go is a safe language? It has garbage collection and performs checks for things like buffer overflows and use-after-free
WRONG!
Plain and simple C is, by far, one of the current _LESS WORSE_ performant alternatives which can be used, actually, from low level to large applications.
C syntax is already waaaaay to rich and complex (and ISO is a bit too much pushing feature creep over 5/10 years cycles).
That's the first time I've heard the C syntax being called "too rich". It's the epitome of succinctness IMHO (too a fault, even, or maybe I'm just old). Are you confusing it with C++? If so, you have a point.
I am talking about C syntax, not absurdely grotesque ultra-complex syntax like the ones from c++, java and similar (is that true that rust syntax is not that much less worse than c++ one now?).
We need a new C, fixed, leaner and less complex: primitives are all sized (u64, u8, f64, etc), only one loop primitive (loop{}), no switch, no enum, no typedef, no typeof and other c11 _generic/etc, no integer promotion, no implicit casts (except for void* and literal numbers?), real hard compiler constants, current "const" must go away (I don't even talk about "restrict" and similar), no anonymous code block, explicit differentiation between reinterpret,runtime,etc casts?, anonymous struct/union for complex memory layouts, and everything else I am currently forgetting about.
(the expression evaluation of the C pre-processor would require serious modifications too)
We need clean and clear cut definitions, in regards of ABIs, of argument passing by value of aggregates like structs/arrays, you know, mostly for those pesky complex numbers and div_t.
We need keywords and official very-likely-to-be-inline-or-hardware-accelerated-functions, something in between the standard library and the compiler keywords, for modern hardware architecture programming like memory barriers, atomics, byte swapping, some bitwise operations (like popcnt), memcpy, memcmp, memmove, etc.
In the end, I would prefer to have a standard machine ISA (RISC-V) and code everything directly in assembly, or with very high level languages (like [ecma|java]script, lua, etc) with a interpreter coded in that standard machine ISA assembly (all that with a reasonable SDK, ofc)
C's syntax is pretty lacking by modern standards, requiring gross things like The Lexer Hack to resolve ambiguities that other languages just don't suffer from: https://en.wikipedia.org/wiki/Lexer_hack . To say nothing of the madness that is C's type declaration syntax, necessitating tools like https://cdecl.org/ and "the spiral rule" for reading type declarations (which doesn't actually produce the correct result anyway).
As a Lisper I would consider C having too much syntax. 3 different kinds of brackets, a mix of prefix, suffix, and infix operators, both dot and hyphen + greater than symbol infixes for member access on structures depending on whether you're accessing members of a struct directly or from a struct pointer, semicolons at the end of every statement, the different ways of declaring imports,...
Huh. I don’t think I miswrote yes I’m talking about a larger language like c++.
Forgot to switch the account?
hahaha
Interesting! Let’s start this debate!
I love C, when I wrote my first programs in it as a teenager, I loved the simplicity, I love procedural code. Large languages like C++ and or Rust are just too much for ME. Too much package. I like writing code in a simple way, if I can do that with a small amount of tools, I will. You can learn C and be efficient in it within a couple weeks. C systems are just built better, faster, more stable, portable, and more! This is my 2 cents.
C is considered harmful. They should rewrite it in Rust.
> They should rewrite it in Rust.
Why they? You should do it.
What
They actually should. As such a rewrite went so well for sudo-rs.
The article mentions 100% code coverage with tests as one of requirements from their users, and having "safe languages" emit defensive asserts and checks when compiling correct code means 100% branch coverage is impossible. How do you propose to address it with rust?
It's either trolling or sarcasm. May be both.
Not trolling. Everyone knows C is not safe.
C is safe if you know how to write it. Jokes aside yes you need to be more careful.
Life as a whole is not safe, and not everyone seems to be aware of this.
> strangely and disproportionately pushed on Hacker News
There is literally nothing strange or disproportionate. It's incredibly obvious that new languages, that were designed by people who found older languages lacking, are of interest to groups of people interested in new applications of technology and who want to use their new languages.
> then those from outside the project shouldn't really have any say on it. It's their project.
People outside the project are allowed to say whatever the hell they want, the project doesn't have to listen.
I think it's more than just the normal amount for advocacy of a new language. Rust isn't the only "newer" language. I don't feel this kind of mentally strung pushing of say Kotlin or Scala or Go or, etc from their fans.
I think this is because of the gap in its target market -- Rust is firmly positioned to replace C and C++, which have a long history of safety issues. Kotlin is positioned to replace java, and besides a few quality-of-life improvements, it changes some syntax but very few semantics, so the gap is much smaller. Go was originally pitched as a C or C++ replacement, and it's very nice for deeply parallel programs like web services, but its big runtime and its GC rule it out for a lot of (especially very low level or latency-critical) uses -- you don't see Go ported to microcontrollers for instance. I can't speak for Scala, because i don't have experience writing software in it.
To summarize, Rust provides a lot of compile-time discipline that C and C++ are lacking, and many people are tired of maintaining code that was developed without that discipline. Rust makes it harder to write low-effort software.
As a programmer that picks up a new language every 2-3 years (and one that is privileged to have an employer that tolerates this) Rust is really a breath of fresh air; not because it's easier, but because it codifies and enforces some good habits in ways that other languages don't.
There is no chance that Kotlin will replace Java. Java is the platform and Kotlin does change semantics. They’ve developed their own features that don’t align with the platform. Suspend functions vs virtual threads, data classes vs records, Kotlin value classes vs Java value classes. The gap is widening.
I do deploy things in different languages -- We are a small team of open-minded programmers, and we are on a constant search for better tools and methods. I work for a robotics company (and have for many years), and having the flexibility to use Pion WebRTC (in Go) or PCL (in C++) or PyTorch (in Python) outweighs the cost of having software written in multiple languages.
Kotlin won't replace Java. They do not have the same niche.
Love to see an AI agent to auto transpile C (sqlite, apache, nginx, mariadb, etc) into rust and run all the regression associated tests and perf benchmarks and produce report on the porting processes and perf delta.
> Surely that gap has been filled for at least a decade, even if only by Rust itself?
I think this is the argument made by the "Rust Evangelism Task Force" -- that Rust provides the features that C and C++ are missing. What i meant by "gap" is "the distance between C or C++ and Rust is greater then the distance between C++ and Go (in Go's target use case) or between Java and Kotlin". For the record, I do think all of these languages are great; I'm just trying to reason out the "rewrite it in Rust" mantra that has taken hold in many online communities, including this one.
> You don't? https://tinygo.org
I wasn't aware of this, thank you.
Is it really activism though, i.e. a concerted effort to put pressure on project leaders and make actual "demands"? Or is it just the occasional young Rust enthusiast asking questions or making the case for Rust?
I'm not a Rust evangelist, but I'm glad that Rust evangelists exist.
I decided to try it for a medium-sized (~10k LoC) performance sensitive component recently and it has been an absolute joy to use.
I'm mostly a Java dev, but baby-stepping Rust has been a lot of fun and reminds me, in a very good way, of the feeling I had in the late 90's when I was first learning Java.
I think that's true - but I guess Rust and Zig are unique in that list on being new memory-managed languages (i.e. without garbage collectors).
Low level memory-managed languages have been C and C++ mostly for a really long time, so I think Rust and Zig probably seem "more new" than the likes of Kotlin, Go, Elixir, Gleam, etc.
Can I start then with Scala - it's my favorite language and easily has the best of both OO and functional worlds with insanely useful libraries to express code ergonomically. EVERYBODY SHOULD USE IT!
I worked on a Scala project about 15 years ago and it definitely felt overly complex. Similar to early C++, everyone used their own dialect.
Always gotta get my yum yucked.
Yeah, I agree with this observation. Not sure why Rust is different here though.
I understand "shouldn't really have any say on it" as shouldn't expect to infuence the project. Not that they are not allowed to say anything.
Otherwise they would have written something along the lines of "shouldn't say anything about it".
> People outside the project are allowed to say whatever the hell they want, the project doesn't have to listen.
Within reason - don't be a dick and all that. :)
I am pretty certain Rust is pushed more than other languages. Whether warranted or not is another topic, but I think the OP has a point here.
"having a say on something", in OP's context, means authority and influence over decisions... People can say whatever they want, yes, but not everyone can "have a say on something".
> People outside the project are allowed to say whatever the hell they want,
And? GP didn't say that they shouldn't.
> People outside the project are allowed to say whatever the hell they want
What these people do is a disservice to the general open source community, by spreading misinformation and general FUD about critical software that uses C and C++.
Rust is pushed on the internet
I definitely wouldn't say internet, I think it's popular on HN and a few other online forums. There are a lot of X/twitter circles which make are critical of rust, as well as other sites.
In my mind at least there's a decent risk Rust is going to end up like the next Haskell, its benefits other than safety are not that clear and many of those features can and have been replicated in other languages.
It is also worth to note that the Rust design, in its theory, and the recent bug in the Linux kernel Rust code (the message passing abstraction used by Android), makes clear that:
1. With Rust, you may lower the exposure, but the same classes of bug still remain. And of course, all the other non memory related bugs.
2. With C you may, if you wish, develop a big sensibility to race conditions, and stay alert. In general it is possible that C programmers have their "bugs antenna" a bit more developed than other folks.
3. With Rust, to decrease the "unsafe" sections amount, you need often to build abstractions that may be a bit unnatural.
4. Rust may create a false sense of security, and in the unsafe sections the programmer sometimes, when reviewing the code, is falsely convinced by the mandatory SAFETY comment. Like in the Linux Kernel bug, where such comment was hallucinated by a human that sometimes (not sure in this specific case, it's just an example) may be less used to do the "race spotting" process that C learns you to do.
5. With Rust, in case of a bug, the fix could no longer be the one-liner usually you see in C fixes, and can make the exposure time window larger. Sometimes fixing things in Rust means refactoring in non trivial ways.
6. With C, if there was the same amount of effort in creating wrappers to make kernel programming safer at the cost of other things, the surface of attack could also be lowered in a significant way (see for instance Redis use of sds.c: how many direct strings / pointers manipulation we avoid? The same for other stuff of course). Basically things like sds.c let you put a big part of the unsafe business in a self contained library.
So, is Rust an interesting language for certain features it has? Yes. Is Rust a silver bullet? No. So should Rust be "pushed" to others, hell no, and I suggest you to reply in the most firm way to people stressing you out to adopt Rust at all the costs.
The recent bug in the Linux kernel Rust code, based on my understanding, was in unsafe code, and related to interop with C. So I wouldn't really classify it as a Rust bug. In fact, under normal circumstances (no interop), people rarely use unsafe in Rust, and the use is very isolated.
I think the idea of developers developing a "bugs antenna" is good in theory, though in practice the kernel, Redis, and many other projects suffer from these classes of bugs consistently. Additionally, that's why people use linters and code formatters even though developers can develop a sensitivity to coding conventions (in fact, these tools used to be unpopular in C-land). Trusting humans develop sensibility is just not enough.
Specifically, about the concurrency: Redis is (mostly) single-threaded, and I guess that's at least in part because of the difficulty of building safe, fast and highly-concurrent C applications (please correct me if I'm wrong).
Can people write safer C (e.g. by using sds.c and the likes)? For sure! Though we've been writing C for 50+ years at this point, at some point "people can just do X" is no longer a valid argument. As while we could, in fact we don't.
> was in unsafe code, and related to interop with C
1) "interop with C" is part of the fundamental requirements specification for any code running in the Linux kernel. If Rust can't handle that safely (not Rust "safe", but safely), it isn't appropriate for the job.
2) I believe the problem was related to the fact that Rust can't implement a doubly-linked list in safe code. This is a fundamental limitation, and again is an issue when the fundamental requirement for the task is to interface to data structures implemented as doubly-linked lists.
No matter how good a language is, if it doesn't have support for floating point types, it's not a good language for implementing math libraries. For most applications, the inability to safely express doubly-linked lists and difficulty in interfacing with C aren't fundamental problems - just don't use doubly-linked lists or interface with C code. (well, you still have to call system libraries, but these are slow-moving APIs that can be wrapped by Rust experts) For this particular example, however, C interop and doubly-linked lists are fundamental parts of the problem to be solved by the code.
> If Rust can't handle that safely (not Rust "safe", but safely), it isn't appropriate for the job.
Rust is no less safe at C interop than using C directly.
I hear "people rarely use unsafe rust" quite a lot, but every time I see a project or library with C-like performance, there's a _lot_ of unsafe code in there. Treating bugs in unsafe code as not being bugs in rust code is kind of silly, also.
For replacing a Python project with Rust, unsafe blocks will comprise 0% of your code. For replacing a C project with Rust, unsafe blocks will comprise about 5% of your code. The fact that the percentage is higher in the latter case doesn't change the fact that 95% of your codebase is just as safe as the Python project would be.
In Rust you can avoid "unsafe" when you use Rust like it was Go or Python. If you write low level code, that is where C is in theory replaceable only by Rust (and not by Go), then you find yourself in need of writing many unsafe sections. And to lower the amount of unsafe sections, you have to build unnatural abstractions, often, in order to group such unsafe sections into common patterns. Is is a tradeoff, not a silver bullet.
Not necessarily at all. Go peruse the `regex` crate source code, including its dependencies.
The biggest `unsafe` sections are probably for SIMD accelerated search. There's no "unnatural abstractions" there. Just a memmem-like interface.
There's some `unsafe` for eliding bounds checks in the main DFA search loops. No unnatural abstractions there either.
There's also some `unsafe` for some synchronization primitives for managing mutable scratch space to use during a search. A C library (e.g., PCRE2) makes the caller handle this. The `regex` crate does it for you. But not for unnatural reasons. To make using regexes simpler. There are lower level APIs that provide the control of C if you need it.
That's pretty much it. All told, this is a teeny tiny fraction of the code in the `regex` crate (and all of its dependencies).
Finally, a demonstration of C-like speed: https://github.com/BurntSushi/rebar?tab=readme-ov-file#summa...
> Is is a tradeoff, not a silver bullet.
Uncontroversial.
I think this framing is a bit backwards. Many C programs (and many parts of C programs) would benefit from being more like Go or Python as evident by your very own sds.c.
Now, if what you're saying is that with super highly optimized sections of a codebase, or extremely specific circumstances (some kernel drivers) you'd need a bit of unsafe rust: then sure. Though all of a sudden you flipped the script, and the unsafe becomes the exception, not the rule; and you can keep those pieces of code contained. Similarly to how C programmers use inline assembly in some scenarios.
Funny enough, this is similar to something that Rust did the opposite of C, and is much better for it: immutable by default (let mut vs. const in C) and non-nullable by default (and even being able to define something as non-null). Flipping the script so that GOOD is default and BAD is rare was a huge win.
I definitely don't think Rust is a silver bullet, though I'd definitely say it's at least a silver alloy bullet. At least when it comes to the above topics.
> With C you may, if you wish, develop a big sensibility to race conditions, and stay alert. In general it is possible that C programmers have their "bugs antenna" a bit more developed than other folks.
I suppose it's possible. I wonder if I'll become a better driver if I take off my seatbelt. Or even better, if I take my son out of my car seat and just let him roam free in the back seat. I'm sure my wife will buy this.
In all seriousness, your comment reminds me of this funny video: https://www.youtube.com/watch?v=glmcMeTVIIQ
It's nowhere near a perfect analogy, but there are some striking similarities.
FWIW, FAFO is a very good way to learn. Assuming we can respawn indefinitely and preserve knowledge between respawns, driving fast and taking off your seatbelt would definitely teach you more than just reading a book.
But in this specific case, if the respawn feature is not available or dying isn't a desirable event, FAFO might not be the best way to learn how to drive.
A quick unscientific count on cve.org counts ~86 race condition CVEs in the Linux kernel last year, so you might be overstating how well bug antennas work.
If the kernel was completely written in Rust, we could have a lot of unsafe places, and many Rust CVEs. It is hard to tell, and the comparison in theory should be made after the kernel is developed only by people lacking the C experience that made the current developers so able to reason about race conditions (also when they write Rust).
That's quite the double standard. You extrapolate from one single Rust bug, but insist that "it's hard to tell" and you need completely unrealistic levels of empirical evidence to draw conclusions from the reported C bugs...
Reminds me of this classic: "Beware Isolated Demands For Rigor" (https://slatestarcodex.com/2014/08/14/beware-isolated-demand...)
86 race conditions compared to what baseline? This is a bit meaningless without benchmarking against other kernels
That is no base line. That is a comparison with no statistical value.
But you need to control for lines of code at the very least — otherwise you're comparing apples to oranges
Love it
(2) and (3) just don't seem to be the case empirically. One bug that was directly in a grep'able `unsafe` block is hardly evidence of these, whereas Google's study on Rust has demonstrated (far more rigorously imo) the opposite. I think anyone paying attention would have guessed that the first Rust CVE would be a race - it is notoriously hard to get locking/ race semantics correct in the kernel, not even the C programmers get it right, it's an extremely common bug class and I believe Linus has basically said something along the lines of "no one understands it" (paraphrasing).
(4) Again, this doesn't seem to be borne out empirically.
(5) I've seen plenty of patches to C code that are way more than a single line for the Linux kernel, but sure, maybe we grant that a bug fix in Rust requires more LOC changed? It'd be nice to see evidence. Is the concern here that this will delay patching? That seems unlikely.
It's not uncommon at all for patches to the C code in the kernel for "make this generally safe" are 1000s of lines of code, seeding things like a "length" value through code, and take years to complete. I don't think it's fair to compare these sorts of "make the abstraction safe" vs "add a single line check" fixes.
(6) Also not borne out. Literally billions spent on this.
> So, is Rust an interesting language for certain features it has? Yes. Is Rust a silver bullet? No.
Agreed. I'm tempted to say that virtually no one contests the latter lol
> So should Rust be "pushed" to others, hell no, and I suggest you to reply in the most firm way to people stressing you out to adopt Rust at all the costs.
I guess? You can write whatever you want however you want, but users who are convinced that Rust code will provide a better product will ask for it, and you can provide your reasoning (as SQLite does here, very well imo) as firm as you'd please I think.
edit: And to this other comment (I'm rate limited): https://news.ycombinator.com/item?id=46513428
> made the current developers so able to reason about race conditions (also when they write Rust).
Aha. What? Where'd you get this from? Definitely not from Linus, who has repeatedly stated that lock issues are extremely hard to detect ahead of time.
> we’ve tweaked all the in-kernel locking over decades [..] and even people who know what they are doing tend to get it wrong several times
https://lwn.net/Articles/808498/
Definitely one of MANY quotes and Linus is not alone.
Google have published a couple high-level Rust blog posts with many graphs and claims, but no raw data or proofs, so they haven’t demonstrated anything.
By now their claims keep popping up in Rust discussion threads without any critical evaluation, so this whole communication is better understood as a marketing effort and not a technical analysis.
> Google have published a couple high-level Rust blog posts with many graphs and claims, but no raw data or proofs, so they haven’t demonstrated anything.
Don't expect proofs from empirical data. What we have is evidence. Google has published far better evidence, in my view, than "we have this one CVE, here are a bunch of extrapolations".
> By now their claims keep popping up in Rust discussion threads without any critical evaluation,
Irrelevant to me unless you're claiming that I haven't critically evaluated the information for some reason.
Is there still pressure to use OOP? On Hacker News, at least, the trend seems to be moving in the opposite direction. There’s growing skepticism toward OOP, and that’s reflected in the popularity of languages like Rust and Zig, which are explicitly designed to push against traditional object-oriented patterns.
That’s not to say OOP advocacy has disappeared from HN. It still exists, but it no longer feels dominant or ascendant. If anything, it feels like a legacy viewpoint maintained by a sizable but aging contingent rather than a direction the community is moving toward.
Part of OOP’s staying power comes from what I’d call a cathartic trap. Procedural programming is intuitive and straightforward. OOP, by contrast, offers a new conceptual lens: objects, inheritance, polymorphism, and eventually design patterns. When someone internalizes this framework, there’s often a strong moment of “clicking” where complex software suddenly feels explainable and structured. That feeling of insight can be intoxicating. Design patterns, in particular, amplify this effect by making complexity feel principled and universally applicable.
But this catharsis is easy to confuse with effectiveness. The emotional satisfaction of understanding a system is orthogonal to whether that system actually produces better outcomes. I’ve seen a similar dynamic in religion, where the Bible’s dense symbolism and internal coherence produce a powerful sense of revelation once everything seems to “fit” together. The feeling is real, but it doesn’t validate the underlying model.
In practice, OOP often increases complexity and reduces modularity. This isn’t always obvious from inside the paradigm. It tends to become clear only after working seriously in other paradigms, where composition, data-oriented design, or functional approaches make the tradeoffs impossible to ignore.
In my circles, there is one part of OOP seen as positive: encapsulation. Everything else, specially inheritance and partly polymorphism are seen extremely negatively. The hype is over. BUT: I still hear more often as I would like, some manager stating “of course we will use C++, because is THE OOP language, and everybody knows OOP and UML are the only right way of doing software” this is an actual verbatim statement I had to listen 4 years ago.
It should not be strange that a tool which is better in every way and makes your code less buggy by default has its praises sung by most of the people who use it. It would be odd to go around saying 'electric drills are strangely and disproportionately pushed at Home Depot over the good old hand auger', and even if I don't work at your contracting company I'd be slightly unnerved about you working on my house.
I’ve heard this analogy used to justify firing developers for not using GenAI: a cabinet maker who doesn’t use power tools shouldn’t be working as a cabinet maker.
If only programming languages (or GenAI) were tools like hammers and augers and drills.
Even then the cabinets you see that come out of shops that only use hand tools are some of the most sturdy, beautiful, and long lasting pieces that become the antiques. They use fewer cuts, less glue, avoid using nails and screws where a proper joint will do, etc.
Less glue and avoidance of nails and screws doesn't make it sturdier. Fastening things strongly makes your furniture sturdier than not doing so. Antiques suck as often as they don't, and moreover you are only seeing the ones that survived without a base rate to compare it to; they succeeded in spite of power tools, but power tools would have made the same object better.
Comparing it to AI makes no sense. Invoking it is supposed to bring to mind the fact that it's worse in well-known ways, but then the statement 'better in every way' no longer applies. Using Rust passively improves the engineering quality compared to using anything else, unlike AI which sacrifices engineering quality for iteration speed.
> Less glue and avoidance of nails and screws doesn't make it sturdier. Fastening things strongly makes your furniture sturdier than not doing so.
No disrespect intended, but your criticism of the analogy reveals that you are speaking from assumptions, but not knowledge, about furniture construction.
In fact, less glue, and fewer fasteners (i.e. design that leverages the strength of the materials), is exactly how quality furniture is made more sturdy.
The topic seems to be native programming languages -- I don't think any of the languages concerned are "better in every way" for every possible coding problem. Many will rightfully choose Fortran over Rust for their application -- knowing full well their choice is far away from "better in every way".
The thing is that more than a few people disagree that it is better in every way.
I'm very much into Rust but this article is precisely about the fact that Rust is not "better in every way"...
This article was written nine years ago, when Rust 1.0 was two years old, by an author who spent a small (but nonzero) amount of time evaluating Rust.
Given the author's misunderstanding of what Rust provides, the most charitable interpretation is that they haven't updated the parts discussing Rust since 2017. If they had, it would reflect more poorly on them.
Not true, the page is updated every now and again.
Bad analogy.
If the alternative has drawbacks (they always do) or is not as well known by the team, it's perfecly fine to keep using the tool you know if it is working for you.
People who incessantly try to evangelise their tool/belief/preferences to others are often seen as unpleasant to say the least and they often achieve the opposite effect of what they seek.
of course there are drawbacks to power tools. you could run out of battery for example and now its useless.
but everyone with a brain knows the costs are worth the benefits.
I was talking in general if that escaped you. Hence "beliefs/preferences" and not only tools.
And when it comes to programming languages, it's not as clear cut. As exemplified by the article.
So the power tools is a poor analogy.
I mostly agree, but the OOP is most definitely not in vogue on HN for the past decade at least, arguably far longer than that (think Rust pre-1.0, Go 1.0 times).
Absolutely. Our thought leaders have been pushing functional programming for a long time now.
Is it possible to have an OOP language which is also functional? Or is it impossible without imperative paradigms?
There's some muddiness in the terminology here -- OOP is really a design style, and "OOP languages" are generally imperative languages that have sematics that encourage OOP design. It is very possible, even encouraged, to represent state as "Objects" in many functional languages; it's just not really enforced by the language itself.
A good example of this are the object systems in Scheme and Common Lisp (which are less strictly Functional (note the capital F in that word) then something like Haskell).
Context: Along with the never ending pressure to migrate a project to new shiny, there is a lot of momentum against C and other memory-unsafe languages.
The US government recently called on everyone to stop using them and move to memory-safe languages.
Regardless, there are practices and tools that significantly help produce safe C code and I feel like more effort should be spent teaching C programmers those.
Edit: Typos and to make the point that I'm not necessarily defending C, just acknowledging it's place. I haven't written a significant amount of C in over 2 decades, probably, aside from microcontroller C.
C was my first language, more than thirty years ago. I've heard (and probably myself made) the same arguments over and over and over. But those arguments are lame and wrong.
C cannot be made safe (at scale). It's like asbestos. In fact, C is a hazardous material in exactly the same way as asbestos. Naturally occurring, but over industrialized and deployed far too widely before its dangers were known. Still has its uses but it will fuck you up if you do not use industrial-grade PPE.
Stop using C if you can. Stop arguing other people should use it. There have always been alternatives and the opportunity cost of ecosystems continuing to invest in C has massive externalized costs for the entire industry and society as a whole.
> in exactly the same way
C is not known to the state of California to cause cancer.
Not yet
Asbestos causes mesothelioma and gruesome death. C does not. Be serious.
> When C code is run in machines capable of failing with gruesome death, its unsafeness may indeed result in gruesome death.
And yet, it never does. It's been powering those types of machines likely longer than you have been alive, and the one exception I can think of where lives were lost, the experts found that the development process was at fault, not the language.
If it was as bad as you make out, we'd have many many many occurrences of this starting in the 80s. We don't.
Stop spreading FUD.
But oddly enough, Zig is not a memory-safe language, and yet still heavily pushed on here. There are a number of measures, comparatively, that can be taken to make C safer too. The story on what can be done with C is still evolving, as Fil-C and other related projects shows.
For that matter, there are a number of compiled memory-safe and safer languages: Dlang, Vlang, Golang, etc... who could be discussed and are equally viable choices. And if we are talking about something that needs to be outright safety-critical, Ada and SPARK should definitely be in the debate.
However, all of that doesn't override the right of projects to decide on what language they believe is best for them or what strategies concerning safety that they wish to pursue.
Now imagine if every CVE was actually fixed.
How would the three letter agencies then spy on people and deliver their payloads on various target devices?
The governments around the world really need the security holes to exist despite what they say.
> The US government recently called on everyone to stop using them and move to memory-safe languages.
The US government also _really_ (no sarcasm) cares about safety-critical code that can be formally verified, depending on program requirements. DO-178, LOR1, el. al.
Developing those toolchains costs tens of millions, getting them certified costs tens of millions, and then buying those products to use costs 500k-1.5m a pop.
Those toolchains do not exist for rust. I am only aware of these toolchains existing for C, and old C at that.
Hell, rust doesn't even have a formal spec, which is a bit of a roadblock.
https://blog.pictor.us/rust-is-do-178-certifiable/
https://ferrocene.dev/
DO-178C isn’t there yet, but I believe I heard that it’s coming. In general, Ferrous Systems works with customer demand, which has been more automotive to start.
The DOD also made the Waterfall method THE standard software development process.
Department of Waterfall?
> The DOD also made the Waterfall method THE standard software development process.
I'm sure they also made a few bad decisions too :-P
> a bit less in recent years, to use OOP.
That’s an understatement.
> Every project and programmer shouldn't feel they have to justify their choice not to use Rust
Maybe writing about it was taken as an opportunity to clarify their own thinking about the topic?
I get asked this all the time regarding TidesDB. Why didn’t you choose Rust? Well.
Yeah this super common. Great comment.
We (especially management) are trained to always want shiny new thing. Also it's an easy line of dialogue.
Funny how managers get blamed for both wanting new things and for not wanting new things. In the Java 6 days every dev wanted to upgrade to 7 and later 8… but the meme was that their manager wouldn’t ever let them.
Every serious project should be able to justify its choice of tools. "Because I feel like it" is fine for hobby projects or open-source passion projects, but production-worthy software should have reasoning behind its choices. That reasoning can be something like "it's most effective for us because we know it better" but it should be a deliberate, measured choice.
SQLite is an example of an extremely high quality software project. That encompasses not only the quality of the software itself, but the project management around it. That includes explaining various design choices, and this document explaining the choice of language is just one of many such explanations.
Indeed, indeed.
OOP was always debatable, but with the rise of AI agents I'd go so far as to say it's objectively bad now. AI is much better at reasoning about pure function grammars than imperative classes with inheritance; abstractions that aren't airtight are bug factories.
Yeah, results are what matters. SQLite's process seems to produce solid bug-free results.
My only complaint would be that there's many SQL features I want to use which aren't supported. Surely some part of that is deliberately restricted scope, but some might also be dev velocity issues.
DuckDB (C++) can be used like an SQLite with more SQL features, but it's also a lot buggier. Segfaults from your database are not what you want.
So still hoping for some alternative to come along (or maybe I'll need to write it myself)
What isn't supported? After window functions were added, what else is missing?
The ones that come to mind immediately are more ALTER statements (especially adding non-virtual columns), DATE, TIME, and TIMESTAMP types and their associated functions, and ARRAY types. Although I don't wish to disparage SQLite, they do support a lot of features. Just that I constantly run into the ones they don't, with my use cases.
And beyond standard SQL, stuff like hashmap/bloom filter/vector indices, nearest neighbor search, etc...