bfkwlfkjf 5 hours ago

> Safe languages insert additional machine branches to do things like verify that array accesses are in-bounds. In correct code, those branches are never taken. That means that the machine code cannot be 100% branch tested, which is an important component of SQLite's quality strategy.

Huh it's not everyday that I hear a genuinely new argument. Thanks for sharing.

  • Aurornis 4 hours ago

    I guess I don’t find that argument very compelling. If you’re convinced the code branch can’t ever be taken, you also should be confident that it doesn’t need to be tested.

    This feels like chasing arbitrary 100% test coverage at the expense of safety. The code quality isn’t actually improved by omitting the checks even though it makes testing coverage go up.

    • estebank 4 hours ago

      In safety critical spaces you need to be able to trace any piece of a binary back to code back to requirements. If a piece of running code is implicit in code, it makes that traceability back to requirements harder. But I'd be surprised if things like bounds checks are really a problem for that kind of analysis.

      • Aurornis 11 minutes ago

        I don’t see the issue. The operations which produce a bounds check are traceable back to the code which indexes into something.

      • refulgentis 4 hours ago

        Yeah sounds too clever by half, memory safe languages are less safe because they have bounds checks...maybe I could see it on a space shuttle? Well, only in the most CYA scenarios, I'd imagine.

        • sgarland 4 hours ago

          Bear in mind that SQLite is used in embedded systems, and I absolutely wouldn’t be surprised to learn it’s in space.

        • manwe150 4 hours ago

          Critical applications like that used to use ADA to get much more sophisticated checking than just bounds. No certified engineer would (should) ever design a safety critical system without multiple “unreachable” fail safe mechanisms

          Next they’ll have to tell me about how they had to turn off inlining because it creates copies of code which adds some dead branches. Bounds checks are just normal inlined code. Any bounds checked language worth its salt has that coverage for all that stuff already.

    • nimih 2 hours ago

      > If you’re convinced the code branch can’t ever be taken, you also should be confident that it doesn’t need to be tested.

      I don't think I would (personally) ever be comfortable asserting that a code branch in the machine instructions emitted by a compiler can't ever be taken, no matter what, with 100% confidence, during a large fraction of situations in realistic application or library development, as to do so would require a type system powerful enough to express such an invariant, and in that case, surely the compiler would not emit the branch code in the first place.

      One exception might be the presence of some external formal verification scheme which certifies that the branch code can't ever be executed, which is presumably what the article authors are gesturing towards in item D on their list of preconditions.

      • timv 21 minutes ago

        The argument here is that they're confident that the bounds check isn't needed, and would prefer the compiler not insert one.

        The choices therefore are:

        1. No bound check

        2. Bounds check inserted, but that branch isn't covered by tests

        3. Bounds check inserted, and that branch is covered by tests

        I'm skeptical of the claim that if (3) is infeasible then the next best option is (1)

        Because if it is indeed an impossible scenario, then the lack of coverage shouldn't matter. If it's not an impossible scenario then you have an untested case with option (1) - you've overrun the bounds of an array, which may not be a branch in the code but is definitely a different behaviour than the one you tested.

    • Deanoumean 3 hours ago

      You didn't understand the argument. The testing is what instills the confidence.

  • jonahx 5 hours ago

    So is the argument that safe langs produce stuff like:

        // pseudocode
        if (i >= array_length) panic("index out of bounds")
    
    that are never actually run if the code is correct? But (if I understand correctly) these are checks implicitly added by the compiler. So the objection amounts to questioning the correctness of this auto-generated code, and is predicated upon mistrusting the correctness of the compiler? But presumably the Rust compiler itself would have thorough tests that these kinds of checks work?

    Someone please correct me if I'm misunderstanding the argument.

    • btilly 4 hours ago

      One of the things that SQLite is explicitly designed to do is have predictable behavior in a lot of conditions that shouldn't happen. One of those predictable behavior is that it does its best to stay up and running, and continuing to do the best it can. Conditions where it should succeed in doing this include OOM, the possibility of corrupted data files, and (if possible) misbehaving CPUs.

      Automatic array bounds checks can get hit by corrupted data. Thereby leading to a crash of exactly the kind that SQLite tries to avoid. With complete branch testing, they can guarantee that the test suite includes every kind of corruption that might hit an array bounds check, and guarantee that none of them panic. But if the compiler is inserting branches that are supposed to be inaccessible, you can't do complete branch testing. So now how do you know that you have tested every code branch that might be reached from corrupted data?

      Furthermore those unused branches are there as footguns which are reachable with a cosmic ray bit flip, or a dodgy CPU. Which again undermines the principle of keeping running if at all possible.

      • vlovich123 2 hours ago

        In rust at least you are free to access an array via .get which returns an option and avoids the “compiler inserted branch” (which isn’t compiler inserted by the way - [] access just implicitly calls unwrap on .get and sometimes the compiler isn’t able to elide).

        Also you rarely need to actually access by index - you could just access using functional methods on .iter() which avoids the bounds check problem in the first place.

        • OptionOfT 32 minutes ago

          For slices the access is handled inside of the compiler: https://github.com/rust-lang/rust/blob/235a4c083eb2a2bfe8779...

          I'm checking to see how array access is implemented, whether through deref to slice, or otherwise.

          • vlovich123 30 minutes ago

            I had Vec in mind but regardless nothing forces you to use the bounds-checked variant vs one that returns option<t>. And if you really are sure the bounds hold you can always use the assume crate or just unwrap_unchecked explicitly.

      • jemmyw 2 hours ago

        Keeping running if possible doesn't sound like the best strategy for stability. If data was corrupted in memory in a was that would cause a bounds check to fail then carrying on is likely to corrupt more data. Panic, dump a log, let a supervisor program deal with the next step, or a human, but don't keep going potentially persisting corrupted data.

        • hoppp 2 hours ago

          It still needs to detect that there is corrupted data, dump the log and the supervisor would not be the best if it was external since in some runtimes it could be missing, they just build it into it and we came full circle.

    • binary132 4 hours ago

      I think it’s less like doubting that the given panic works and more like an extremely thorough proof that all possible branches of the control flow have acceptable behavior. If you haven’t tested a given control flow, the issue is that it’s possible that the end result is some indeterminate or invalid state for the whole program, not that the given bounds check doesn’t panic the way it’s supposed to. On embedded for example (which is an important usecase for SQLite) this could result in orphaned or broken resources.

      • jonahx 4 hours ago

        > I think it’s less like doubting that the given panic works and more like an extremely thorough proof that all possible branches of the control flow have acceptable behavior.

        The way I was thinking about it was: if you somehow magically knew that nothing added by the compiler could ever cause a problem, it would be redundant to test those branches. Then wondering why a really well tested compiler wouldn't be equivalent to that. It sounds like the answer is, for the level of soundness sqlite is aspiring to, you can't make those assumptions.

      • thayne 4 hours ago

        But does it matter if that control flow is unreachable?

        If the check never fails, it is logically equivalent to not having the check. If the code isn't "correct" and the panic is reached, then the equivalent c code would have undefined behavior, which can be much worse than a panic.

        • nubbler 2 hours ago

          In the first case, if it is actually unreachable, I would never want that code ending up in my binary at all. It must be optimised out.

          Your second case implies that it is reachable.

    • oconnor663 5 hours ago

      > questioning the correctness of this auto-generated code

      I wouldn't put it that way. Usually when we say the compiler is "incorrect", we mean that it's generating code that breaks the observable behavior of some program. In that sense, adding extra checks that can't actually fail isn't a correctness issue; it's just an efficiency issue. I'd usually say the compiler is being "conservative" or "defensive". However, the "100% branch testing" strategy that we're talking about makes this more complicated, because this branch-that's-never-taken actually is observable, not to the program itself but to its test suite.

    • NobodyNada 4 hours ago

      > But (if I understand correctly) these are checks implicitly added by the compiler.

      This is a dubious statement. In Rust, the array indexing operator arr[i] is syntactic sugar for calling the function arr.index(i), and the implementation of this function on the standard library's array types is documented to perform a bounds-check assertion and access the element.

      So the checks aren't really implicitly added -- you explicitly called a function that performs a bounds check. If you want different behavior, you can call a different, slightly-less-ergonomic indexing function, such as `get` (which returns an Option, making your code responsible for handling the failure case) or `get_unchecked` (which requires an unsafe block and exhibits UB if the index is out of bounds, like C).

      • nubbler 2 hours ago

        Another commenter in this thread used the phrase "complex abomination" which seems more and more apt the more I learn about Rust.

    • dathinab 3 hours ago

      no it's a (accidental) red Hering argument

      sure safety checks are added but

      it's ignoring that many of such checks get reliably optimized away

      worse it's a bit like saying "in case of a broken invariant I prefer arbitrary potential highly problematic behavior over clean aborts (or errors) because my test tooling is inadequate"

      instead of saying "we haven't found adequate test tooling" for our use case

      Why inadequate? Because technically test setups can use

      1. fault injection to test such branches even if normally you would never hit them

      2. for many of such tests (especially array bound checks) you can pretty reliably identify them and then remove them from your test coverage statistic

      idk. what the tooling of rust wrt this is in 2025, but around the rust 1.0 times you mainly had C tooling you applied to rust so you had problems like that back then.

    • lionkor 5 hours ago

      It's not like that, the compiler explicitly doesn't do compile-time checks here and offloads those to the runtime.

      Rust does not stop you from writing code that accesses out of bounds, at all. It just makes sure that there's an if that checks.

      • selcuka 4 hours ago

        Ok, but you can still test all the branches in your source code and have 100% coverage. Those additional `if` branches are added by the compiler. You are responsible for testing the code you write, not the one that actually runs. Your compiler's test suite is responsible for the rest.

        By the same logic one could also claim that tail recursion optimisation, or loop unrolling are also dangerous because they change the way code works, and your tests don't cover the final output.

        • binary132 4 hours ago

          If they produce control flow _in the executable binary_ that is untested, then they could conceivably lead to broken states. I don’t believe most of those sorts of transformations cause alternative control flows to be added to the executable binary.

          I don’t think anyone would find the idea compelling that “you are only responsible for the code you write, not the code that actually runs” if the code that actually runs causes unexpected invalid behavior on millions of mobile devices.

        • foul 4 hours ago

          >You are responsible for testing the code you write, not the one that actually runs.

          Hipp worked as a military contractor for battleships, furthermore years later SQLite was under contract under every proto-smartphone company in the USA. Under these constraints you maybe are not responsible to test what the compiler spits out across platforms and different compilers, but doing that makes the project a lot more reliable, makes it sexier for embedded and weapons.

        • unclad5968 4 hours ago

          I don't see anything wrong with taking responsibility for the code that actually runs. I would argue it's that level of accountability has played a part in Sqlite being such a great project.

        • estebank 4 hours ago

          > You are responsible for testing the code you write, not the one that actually runs.

          This is not correct for every industry.

  • anitil 5 hours ago

    It's the sort of argument that I wouldn't accept from most people and most projects, but from Dr Hipp isn't most people and Sqlite isn't most projects.

    • cogman10 4 hours ago

      It's a bad argument.

      Certainly don't get me wrong, SQLite is one of the best and most thoroughly tested libraries out there. But this was an argument to have 4 arguments. That's because 2 of the arguments break down as "Those languages didn't exist when we first wrote SQLite and we aren't going to rewrite the whole library just because a new language came around."

      Any language, including C, will emit or not emit instructions that are "invisible" to the author. For example, whenever the C compiler decides it can autovectorize a section of a function it'll be introducing a complicated set of SIMD instructions and new invisible branch tests. That can also happen if the C compiler decides to unroll a loop for whatever reason.

      The entire point of compilers and their optimizations is to emit instructions which keep the semantic intent of higher level code. That includes excluding branches, adding new branches, or creating complex lookup tables if the compiler believes it'll make things faster.

      Dr Hipp is completely correct in rejecting Rust for SQLite. Sqlite is already written and extremely well tested. Switching over to a new language now would almost certainly introduce new bugs that don't currently exist as it'd inevitably need to be changed to remain "safe".

      • Ferret7446 2 hours ago

        > Any language, including C, will emit or not emit instructions that are "invisible" to the author

        Presumably this is why they do 100% test coverage. All of those instructions would be tested and not invisible to the test suite

      • manwe150 3 hours ago

        If it was as completely tested as claimed, then switching to rust would be trivial. All you need to do is pass the test suite and all bugs would be gone. I can think of other reasons not to jump to rust (it is a lot of code, sqlite already works well, and test coverage is very good but also incomplete, and rust only solves a few correctness problems)—just not because of claiming sqlite is already tested enough to be bug free of the kinds of issues that rust might actually prevent.

        • dathinab 3 hours ago

          > to rust would be trivial.

          no, you still need to rewrite, re-optimize, etc. everything

          it would make it much easier to be fully compatible, sure, but that doesn't make it trivial

          furthermore part of it's (mostly internal) design are strongly influenced by C specific dev-UX aspects, so you wouldn't write them the same, so test for them (instead of integration tests) may not apply

          which in general also means that you most likely would break some special purpose/usual user which do have "brittle" (not guaranteed) assumptions about SQLite

          if you have code which very little if at all changes and has no major issues, don't rewrite it

          but most of the new "external" things written around SQLite, alternative VFS impl. etc. tend to be at most partially written in C

  • ChadNauseam 5 hours ago

    I wonder if this problem could be mitigated by not requiring coverage of branches that unconditionally lead to panics. or if there could be some kind of marking on those branches that indicate that they should never occur in correct code

    • accelbred 4 hours ago

      You'd want to statically prove that any panic is unreachable

  • hypeatei 5 hours ago

    Couldn't a method like `get_unchecked()` be used to avoid the bounds check[0] if you know it's safe?

    0: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.get...

    • oconnor663 4 hours ago

      Yes. You have to write `unsafe { ... }` around it, so there's an ergonomic penalty plus a more nebulous "sense that you're doing something dangerous that might get some skeptical looks in code review" penalty, but the resulting assembly will be the same as indexing in C.

      • hypeatei 4 hours ago

        I figured, but I guess I don't understand this argument then. SQLite as a project already spends a lot of time on quality so doing some `unsafe` blocks with a `// SAFETY:` comment doesn't seem unreasonable if they want to avoid the compiler inserting a panic branch for bounds checks.

        • tomjakubowski 6 minutes ago

          In many cases LLVM can prove the bounds check is redundant or otherwise is unnecessary and will optimize it away.

        • Ferret7446 2 hours ago

          If you put unsafe around almost all of your code (array indexing) aren't you better off just writing C?

  • kazinator 3 hours ago

    > In incorrect code, the branches are taken, but code without the branches just behaves unpredictably.

    It's like seat belts.

    E.g. what if we drive four blocks and then the case occurs when the seatbelt is needed need the seatbelt? Okay, we have an explicit test for that.

    But we cannot test everything. We have not tested what happens if we drive four blocks, and then take a right turn, and hit something half a block later.

    Screw it, just remove the seatbelts and not have this insane untested space whereby we are never sure whether the seat belt will work properly and prevent injury!

  • beached_whale 5 hours ago

    I think those branches are often not there because it's provably never going out of bounds. There are ways to ensure the compiler knows the bounds cannot be broken.

  • dathinab 4 hours ago

    the problem is it's kinda an anti argument

    you basically say if deeply unexpected things happen you prefer you program doing widely arbitrary and as such potentially dangerous things over it having a clean abort or proper error. ... that doesn't seem right

    worse it's due to a lack of the used tooling and not a fundamental problem, not only can you test this branches (using fault injection) you also often (not always) can separate them from relevant branches when collecting the branch statistics

    so the while argument misses the point (which is tooling is lacking, not extra checks for array bounds and similar)

    lastly array bounds checking is probably the worst example they could have given as it

    - often can be disabled/omitted in optimized builds

    - is quite often optimized away

    - has often quite low perf. overhead

    - bound check branches are often very easy to identify, i.e. excluding them from a 100% branch testing statistic is viable

    - out of bounds read/write are some of the most common cases of memory unsafety leading to security vulnerability (including full RCE cases)

  • NobodyNada 4 hours ago

    It's interesting to consider (and the whole page is very well-reasoned), but I don't think that the argument holds up to scrutiny. If such an automatic bounds-check fails, then the program would have exhibited undefined behavior without that branch -- and UB is strictly worse than an unreachable branch that does something well-specified like aborting.

    A simple array access in C:

        arr[i] = 123;
    
    ...can be thought of as being equivalent to:

        if (i >= array_length) UB();
        else arr[i] = 123;
    
    where the "UB" function can do literally anything. From the perspective of exhaustively testing and formally verifying software, I'd rather have the safe-language equivalent:

        if (i >= array_length) panic();
        else arr[i] = 123;
    
    ...because at least I can reason about what happens if the supposedly-unreachable condition occurs.

    Dr. Hipp mentions that "Recoding SQLite in Go is unlikely since Go hates assert()", implying that SQLite makes use of assert statements to guard against unreachable conditions. Surely his testing infrastructure must have some way of exempting unreachable assert branches -- so why can't bounds checks (that do nothing but assert undefined behavior does not occur) be treated in the same way?

  • coolThingsFirst 4 hours ago

    This is a dumb argument, it's like saying for a perfect human being there's no need for smart pointers, garbage collection or the borrow checker.

jasonthorsness 5 hours ago

“None of the safe programming languages existed for the first 10 years of SQLite's existence. SQLite could be recoded in Go or Rust, but doing so would probably introduce far more bugs than would be fixed, and it may also result in slower code.”

Modern languages might do more than C to prevent programmers from writing buggy code, but if you already have bug-free code due to massive time, attention, and testing, and the rate of change is low (or zero), it doesn’t really matter what the language is. SQLIte could be assembly language for all it would matter.

saalweachter 5 hours ago

I think beyond the historical reasons why C was the best choice when SQLite was being developed, or the advantages it has today, there's also just no reason to rewrite SQLite in another language.

We don't have to have one implementation of a lightweight SQL database. You can go out right now and start your own implementation in Rust or C++ or Go or Lisp or whatever you like! You can even make compatible APIs for it so that it can be a drop-in replacement for SQLite! No one can stop you! You don't need permission!

But why would we want to throw away the perfectly good C implementation, and why would we expect the C experts who have been carefully maintaining SQLite for a quarter century to be the ones to learn a new language and start over?

  • AdamJacobMuller 3 hours ago

    One good reason is that people have written golang adapters, so that you can use sqlite databases without cgo.

    I agree to what I think you're saying which is that "sqlite" has, to some degree, become so ubiquitous that it's evolved beyond a single implementation.

    We, of course, have sqlite the C library but there is also sqlite the database file format and there is no reason we can't have an sqlite implementation in golang (we already do) and one in pure rust too.

    I imagine that in the future that will happen (pure rust implementation) and that perhaps at some point much further in the future, that may even become the dominant implementation.

  • turtletontine 4 hours ago

    Thanks for this, I fully agree. One frustration I have with the modern moment is the tendency to view anything more than five years old with disdain, as utterly irrelevant and obsolete. Maybe I’m just going old, but I like my technology dependable and boring, especially software. Glad to see someone express respect for the decades of expertise that have gone into things we take for granted.

dathinab 3 hours ago

It's kinda sad to read as most of their arguments might seem right at first but if put under scrutiny really fall apart.

Like why defend C in 2025 when you only have to defend C in 2000 and then argue you have a old, stable, deeply tested, C code base which has no problem with anything like "commonly having memory safety issues" and is maintained by a small group of people very highly skilled in C.

Like that argument alone is all you need, a win, simple straight forward, hard to contest.

But most of the other arguments they list can be picked apart and are only half true.

  • mungaihaha 18 minutes ago

    > But most of the other arguments they list can be picked apart and are only half true

    I'd like to see you pick the other arguments apart

  • Deanoumean 3 hours ago

    The argument you propose only works for justifying a maintenance mode for and old codebase. If you want to take the chance to turn away new developers from complex abominations like C++ and Rust and garbage collected sloths like Java and get them to consider a comparatively simple but ubiquitous language that is C, you have to offer more.

    • dangus 3 hours ago

      Is SQLite looking for new developers? Will they ever need a large amount of developers like a mega-corp that needs to hire 100 React engineers?

      • metaltyphoon 2 hours ago

        No, but as morbid as this sounds, the three(?) devs one day will pass away so now what?

        • hoppp 2 hours ago

          Then the rights will be sold to a FAANG or an open souce fork like libSQL will live on.

  • cmrx64 3 hours ago

    (it’s from 2017)

DarkNova6 5 hours ago

> All that said, it is possible that SQLite might one day be recoded in Rust. Recoding SQLite in Go is unlikely since Go hates assert(). But Rust is a possibility. Some preconditions that must occur before SQLite is recoded in Rust include:

- Rust needs to mature a little more, stop changing so fast, and move further toward being old and boring.

- Rust needs to demonstrate that it can be used to create general-purpose libraries that are callable from all other programming languages.

- Rust needs to demonstrate that it can produce object code that works on obscure embedded devices, including devices that lack an operating system.

- Rust needs to pick up the necessary tooling that enables one to do 100% branch coverage testing of the compiled binaries.

- Rust needs a mechanism to recover gracefully from OOM errors.

- Rust needs to demonstrate that it can do the kinds of work that C does in SQLite without a significant speed penalty.

  • steveklabnik 5 hours ago

    1. Rust has had ten years since 1.0. It changes in backward compatible ways. For some people, they want no changes at all, so it’s important to nail down which sense is meant.

    2. This has been demonstrated.

    3. This one hinges on your definition of “obscure,” but the “without an operating system” bit is unambiguously demonstrated.

    4. I am not an expert here, but given that you’re testing binaries, I’m not sure what is Rust specific. I know the Ferrocene folks have done some of this work, but I don’t know the current state of things.

    5. Rust as a language does no allocation. This OOM behavior is the standard library, of which you’re not using in these embedded cases anyway. There, you’re free to do whatever you’d like, as it’s all just library code.

    6. This also hinges on a lot of definitions, so it could be argued either way.

    • dathinab 3 hours ago

      > 2.

      ironically if we look at how things play out in practice rust is far more suited as general purpose languages then C, to a point where I would argue C is only a general purpose language on technicality not on practical IRL basis

      this is especially ridiculous when they argue C is the fasted general purpose language when that has proven to simply not hold up to larger IRL projects (i.e. not micro benchmarks)

      C has terrible UX for generic code re-use and memory management, this often means that in IRL projects people don't write the fasted code. Wrt. memory management it's not rare to see unnecessary clones, as not doing so it to easy to lead to bugs. Wrt. data structures you write the code which is maintainable, robust and fast enough and sometimes add the 10th maximal simple reimplementation (or C macro or similar) of some data structure instead of using reusing some data structures people spend years of fine tuning.

      When people switched a lot from C to C++ most general purpose projects got faster, not slower. And even for the C++ to Rust case it's not rare that companies end up with faster projects after the switch.

      Both C++ and Rust also allow more optimization in general.

      So C is only fastest in micro benchmarks after excluding stuff like fortran for not being general purpose while itself not really being used much anymore for general purpose projects...

    • hoppp 2 hours ago

      Rust has dependency hell and supply chain attacks like with npm.

      • steveklabnik 2 hours ago

        You control the dependencies you put in Cargo.toml.

        • hoppp an hour ago

          What about the dependencies of your dependencies?

          I don't put too many things in Cargo.toml and it still pulls like a hundred things

          • BrouteMinou a minute ago

            Your system is going to be owned, but at least, it's going to be "memory safely" owned!

            P. S.

            I you don't account all the unsafe sections scattered everywhere in all those dependencies.

    • csande17 3 hours ago

      One question towards maturity: has any working version of the Rust compiler ever existed? By which I mean one that successfully upholds the memory-safety guarantees Rust is supposed to make, and does not have any "soundness holes" (which IIRC were historically used as a blank check / excuse to break backwards compatibility).

      The current version of the Rust compiler definitely doesn't -- there's known issues like https://github.com/rust-lang/rust/issues/57893 -- but maybe there's some historical version from before the features that caused those problems were introduced.

      • steveklabnik 3 hours ago

        Every compiler has soundness bugs. They’re just programs like any other. This isn’t exclusive to Rust.

        • csande17 3 hours ago

          In general, the way Rust blurs the line between "bugs in the compiler" and "problems with how the language is designed" seems pretty harmful and misleading. But it's also a core part of the marketing strategy, so...

          • steveklabnik 2 hours ago

            What makes you say this is a core part of the marketing strategy? I don’t think Rust’s marketing has ever focused on compiler bugs or their absence.

            • csande17 2 hours ago

              You are correct that Rust's marketing does not claim that there are no bugs in its compiler. In fact it does the opposite: it suggests that there are no problems with the language, by asserting that any observed issue in the language is actually a bug in the compiler.

              Like, in the C world, there's a difference between "the C specification has problems" and "GCC incorrectly implements the C specification". You can make statements about what "the C language" does or doesn't guarantee independently of any specific implementation.

              But "the Rust language" is not a specification. It's just a vague ideal of things the Rust team is hoping their compiler will be able to achieve. And so "the Rust language" gets marketed as e.g. having a type system that guarantees memory safety, when in fact no such type system has been designed -- the best we have is a compiler with a bunch of soundness holes. And even if there's some fundamental issue with how traits work that hasn't been resolved for six years, that can get brushed off as merely a compiler bug.

              This propagates down into things like Rust's claims about backwards compatibility. Rust is only backwards-compatible if your programs are written in the vague-ideal "Rust language". The Rust compiler, the thing that actually exists in the real world, has made a lot of backwards-incompatible changes. But these are by definition just bugfixes, because there is no such thing as a design issue in "the Rust language", and so "the Rust language" can maintain its unbroken record of backwards-compatibility.

              • aw1621107 9 minutes ago

                > And even if there's some fundamental issue with how traits work that hasn't been resolved for six years, that can get brushed off as merely a compiler bug.

                Is it getting brushed off as merely a compiler bug? At least if I'm thinking of the same bug as you [0] the discussion there seems to be more along the lines of the devs treating it as a "proper" language issue, not a compiler bug. At least as far as I can tell there hasn't been a resolution to the design issue, let alone any work towards implementing a fix in the compiler.

                The soundness issue that I see more frequently get "brushed off as merely a compiler bug" is the lifetime variance one underpinning cve-rs [1], which IIRC the devs have long decided what the proper behavior should be but actually implementing said behavior is blocked behind some major compiler reworks.

                [0]: https://github.com/rust-lang/rust/issues/57893

                [1]: https://github.com/Speykious/cve-rs

      • dathinab 2 hours ago

        has there ever been a modern optimizing C compiler free of pretty serious bugs? (it's a rhetoric question, there hasn't been any)

    • QuiEgo 3 hours ago

      > Rust has had ten years since 1.0. It changes in backward compatible ways. For some people, they want no changes at all, so it’s important to nail down which sense is meant.

      I’d love to see rust be so stable that MSRV is an anachronism. I want it to be unthinkable you wouldn’t have any reason not to support Rust from forever ago because the feature set is so stable.

    • gerdesj 4 hours ago

      "1. Rust has had ten years since 1.0. ..."

      Rust insists on its own package manager "rustup" and frowns on distro maintainers. When Rust is happy to just be packaged by the distro and rustup has gone away, then it will have matured to at least adolescence.

      • steveklabnik 3 hours ago

        Rust has long worked with distro package maintainers, and as far as I know, Rust is packaged in every major Linux distribution.

        There are other worlds out there than Linux.

        • gerdesj 3 hours ago

          So why insist on rustup?

          • dathinab 2 hours ago

            different goals

            the rust version packaged in distros is for compiling rust code shipped as part of the distro. This means it

            - is normally not the newest version (which , to be clear, is not bad per see, but not necessary what you need)

            - might not have all optional components (e.g. no clippy)

            but if you idk. write a server deployed by you company

            - you likely want all components

            - you don't need to care what version the distro pinned

            - you have little reason not to use the latest rust compiler

            for other use cases you have other reasons, some need nightly rust, some want to test against beta releases, some want to be able to test against different rust versions etc. etc.

            rustup exist (today) for the same reason why a lot of dev projects use project specific copies of all kinds of tooling and libraries which do not match whatever their distro ships: The distro use-case and generic dev-use case have diverging requirements! (Other examples nvm(node), flutter, java etc.).

            Also some distros are notorious for shipping outdated software (debian "stable").

            And not everything is Linux, rustup works on OSX.

          • steveklabnik 2 hours ago

            Distributions generally package the versions of compilers that are needed to build the programs in their package manager. However, many developers want more control than that. They may want to use different versions of the compiler on different projects, or a different version than what’s packaged.

            Basically, people use it because they prefer it.

    • wrs 4 hours ago

      For a little more color on 5, as a user of no_std Rust on embedded processors I use crates like heapless or trybox that provide Vec, String, etc. APIs like the std ones, but fallible.

      Of course, two libraries that choose different no_std collection types can't communicate...but hey, we're comparing to C here.

      • dathinab 2 hours ago

        even OOM isn't that different

        like there are some things you can well in C

        and this things you can do in rust too, through with a bit of pain and limitations to how you write rust

        and then there is the rest which looks "hard but doable" in C, but the more you learn about it the more it's a "uh wtf. nightmare" case where "let's kill+restart and have robustness even in presence of the process/error kernel dying" is nearly always the right answer.

  • casparvitch 5 hours ago

    Why can't `if condition { panic(err) }' be used in go as an assert equivalent?

    • Jtsummers 43 minutes ago

      Because C's assert gets compiled out if you have NDEBUG defined in your program. How do you do conditional compilation in Go (at the level of conditionally including or not including a statement)?

sema4hacker 5 hours ago

"Why SQLite is coded in C..." is an explanation, as documented at sqlite.org.

"Why is SQLite coded in C and not Rust?" is a question, which immediately makes me want to ask "Why do you need SQLite coded in Rust?".

daxfohl 4 hours ago

It sounds like the core doesn't even allocate, and presumably the extended library allocates in limited places using safe patterns. So there wouldn't be much benefit from Rust anyway, I'd think. Had SQLite ever had a memory leak or use-after-delete bug on a production release? If so, that answers the question. But I've never heard of one.

Also, does it use doubly linked lists or graphs at all? Those can, in a way, be safer in C since Rust makes you roll your own virtual pointer arena.

  • dathinab 2 hours ago

    > Had SQLite ever had a memory leak or use-after-delete bug on a production release?

    sure, it's an old library they had pretty much anything (not because they don't know what they are doing but because shit happens)

    lets check CVEs of the last few years:

    - CVE-2025-29088 type confusion

    - CVE-2025-29087 out of bounds write

    - CVE-2025-7458 integer overflow, possible in optimized rust but test builds check for it

    - CVE-2025-6965 memory corruption, rust might not have helped

    - CVE-2025-3277 integer overflow, rust might have helped

    - CVE-2024-0232 use after free

    - CVE-2023-36191 segmentation violation, unclear if rust would have helped

    - CVE-2023-7104 buffer overflow

    - CVE-2022-46908 validation logic error

    - CVE-2022-35737 array bounds overflow

    - CVE-2021-45346 memory leak

    ...

    as you can see the majority of CVEs of sqlite are much less likely in rust (but a rust sqlite impl. likely would use unsafe, so not impossible)

    as a side note there being so many CVEs in 2025 seem to be related to better some companies (e.g. Google) having done quite a bit of fuzz testing of SQLite

    other takeaways:

    - 100% branch coverage is nice, but doesn't guarantee memory soundness in C

    - given how deeply people look for CVEs in SQLite the number of CVEs found is not at all as bad as it might look

    but also one final question:

    SQLite uses some of the best C programmers out there, only they merge anything to the code, it had very limited degree of change compared to a typical company project. And we still have memory vulnerabilities. How is anyone still arguing for C for new projects?

  • thinkharderdev 3 hours ago

    > Also, does it use doubly linked lists or graphs at all? Those can, in a way, be safer in C since Rust makes you roll your own virtual pointer arena.

    You can implement a linked list in Rust the same as you would in C using raw pointers and some unsafe code. In fact there is one in the standard library.

  • steveklabnik 3 hours ago

    Rust’s memory safety guarantees aren’t exclusive to hep allocation. In fact, the language doesn’t heap allocate at all.

    You can write a linked list the same way you would in C if you wish.

pizlonator 5 hours ago

SQLite works great in Fil-C with minimal changes.

So, the argument for keeping SQLite written in C is that it gives the user the choice to either:

- Build SQLite with Yolo-C, in which case you get excellent performance and lots of tooling. And it's boring in the way that SQLite devs like. But it's not "safe" in the sense of memory safe languages.

- Build SQLite with Fil-C, in which case you get worse (but still quite good) performance and memory safety that exceeds what you'd get with a Rust/Go/Java/whatever rewrite.

Recompiling with Fil-C is safer than a rewrite into other memory safe languages because Fil-C is safe through all dependencies, including the syscall layer. Like, making a syscall in Rust means writing some unsafe code where you could screw up buffer sizes or whatnot, while making a syscall in Fil-C means going through the Fil-C runtime.

wodenokoto 5 hours ago

I think it’s more interesting that DuckDB is written in C++ and not rust than SQLite.

SQLite is old, huge and known for its gigantic test coverage. There’s just so much to rewrite.

DuckDB is from 2019, so new enough to jump on the “rust is safe and fast”

  • tonyhart7 5 hours ago

    if they write it on modern C++ then its alright tbh

  • jandrewrogers 5 hours ago

    If maximum performance is a top objective, it is probably because C++ produces faster binaries with less code. Modern C++ specifically also has a lot of nice compile-time safety features, especially for database-like code.

    • wodenokoto 2 hours ago

      I can’t verify those claims one way or another, but I’m interested to hear why they were downvoted.

Jtsummers 6 hours ago

Two previous, and substantial, discussions on this page:

https://news.ycombinator.com/item?id=28278859 - August 2021

https://news.ycombinator.com/item?id=16585120 - March 2018

  • bravura 4 hours ago

    I'm curious about tptacek's comment (https://news.ycombinator.com/item?id=28279426). 'the "security" paragraphs in this page do the rest of the argument a disservice. The fact is, C is a demonstrable security liability for sqlite.'

    The current doc no longer has any paragraphs about security, or even the word security once.

    The 2021 edition of the doc contained this text which no longer appears: 'Safe languages are often touted for helping to prevent security vulnerabilities. True enough, but SQLite is not a particularly security-sensitive library. If an application is running untrusted and unverified SQL, then it already has much bigger security issues (SQL injection) that no "safe" language will fix.

    It is true that applications sometimes import complete binary SQLite database files from untrusted sources, and such imports could present a possible attack vector. However, those code paths in SQLite are limited and are extremely well tested. And pre-validation routines are available to applications that want to read untrusted databases that can help detect possible attacks prior to use.'

    https://web.archive.org/web/20210825025834/https%3A//www.sql...

unsungNovelty an hour ago

As I write more code, use more software and read about rewrites...

The biggest gripe I have with a rewrite is... A lof of the time we rewrite for feature parity. Not the exact same thing. So you are kind ignoring/missing/forgetting all those edge cases and patches that were added along the way for so many niche or otherwise reasons.

This means broken software. Something which used to work before but not anymore. They'll have to encounter all of them again in the wild and fix it again.

Obviously if we are to rewrite an important piece of software like this, you'd emphasise more on all of these. But it's hard for me to comprehend whether it will be 100%.

But other than sqlite, think SDL. If it is to be rewritten. It's really hard for me to comprehend that it's negligible in effect. Am guessing horrible releases before it gets better. Users complaining for things that used work.

C is going to be there long after the next Rust is where my money is. And even if Rust is still present, there would be a new Rust then.

So why rewrite? Rewrites shouldn't be the default thinking no?

kazinator 4 hours ago

> The C language is old and boring. It is a well-known and well-understood language.

So you might think, but there is a committee actively undermining this, not to mention compiler people keeping things exciting also.

There is a dogged adherence to backward compatibility, so that you can't pretend C has not gone anywhere in thirty-five years, if you like --- provided you aren't invoking too much undefined behavior. (You can't as easily pretend that your compiler has not gone anywhere in 35 years with regard to things you are doing out of spec.)

matt3210 5 hours ago

I can compile c anywhere and for any processor, which can’t be said for rust

mikece 8 hours ago

The fact that a C library can easily be wrapped by just about any language is really useful. We're considering writing a library for generating a UUID (that contains a key and value) for reasons that make sense to us and I proposed writing this in C so we could simply wrap it as a library for all of the languages we use internally rather than having to re-implement it several times. Not sure if we'll actually build this library but if we do it will be in C (I did managed to get the "wrap it for each language" proposal pre-approved).

  • mellinoe 5 hours ago

    You can expose a C interface from many languages (C++, Rust, C# to name a few that I've personally used). Instead of introducing a new language entirely, it's probably better to write the library in one of the languages you already use.

  • 01HNNWZ0MV43FF 5 hours ago

    It is. You can also write it in C++ or Rust and expose a C API+ABI, and then you're distributing a binary library that the OS sees as very similar to a C library.

    Occasionally when working in Lua I'd write something low-level in C++, wrap it in C, and then call the C wrapper from Lua. It's extra boilerplate but damn is it nice to have a REPL for your C++ code.

    Edit: Because someone else will say it - Rust binary artifacts _are_ kinda big by default. You can compile libstd from scratch on nightly (it's a couple flags) or you can amortize the cost by packing more functions into the same binary, but it is gonna have more fixed overhead than C or C++.

vincent-manis 5 hours ago

The point about bounds checking in `safe' languages is well taken, it does prevent 100% test coverage. As we all agree, SQLite has been exhaustively tested, and arguments for bounds checking in it are therefore weakened. Still, that's not an argument for replicating this practice elsewhere, not unless you are Dr Hipp and willing to work very hard at testing. C.A.R. Hoare's comment on eliminating runtime checks in release builds is well-taken here: “What would we think of a sailing enthusiast who wears his life-jacket when training on dry land but takes it off as soon as he goes to sea?”

I am not Dr Hipp, and therefore I like run-time checks.

psyclobe 3 hours ago

SQLite is a true landmark, c not withstanding it just happened to be the right tool at the right time and by now anything else is well not as interesting as what they have going on now; totally bucks the trend of throw away software.

pm2222 7 hours ago

These points strike me:

  Safe languages insert additional machine branches to do things like verify that array accesses are in-bounds. In correct code, those branches are never taken. That means that the machine code cannot be 100% branch tested, which is an important component of SQLite's quality strategy.

  Rust needs to mature a little more, stop changing so fast, and move further toward being old and boring.

  Rust needs to demonstrate that it can do the kinds of work that C does in SQLite without a significant speed penalty.
  • steveklabnik 6 hours ago

    If the branch is never taken, and the optimizer can prove it, it will remove the check. Sometimes if it can’t actually prove it there’s ways to help it understand, or, in the almost extreme case, you do what I commented below.

    • sedatk 5 hours ago

      Yeah I don't understand the argument. If you can't convince the compiler that that branch will never be taken, then I strongly suspect that it may be taken.

      • unclad5968 4 hours ago

        That's not the point. The point is that if it is never taken, you can't test it. They don't care that it inserts a conditional OP to check, they care that they can't test the conditional path.

        • sedatk 4 hours ago

          But, there is no conditional path when the type system can assure the compiler that there is nothing to be conditional about. Do they mean that it's impossible to be 100% sure about if there's a conditional path or not?

      • compiler-guy 3 hours ago

        A program can have many properties that the compiler cannot prove statically. To take a very basic case, the halting problem.

  • rstuart4133 7 hours ago

    > Safe languages insert additional machine branches to do things like verify that array accesses are in-bounds. In correct code, those branches are never taken. That means that the machine code cannot be 100% branch tested, which is an important component of SQLite's quality strategy.

    This is annoying in Rust. To me array accesses aren't the most annoying, it's match{} branches that will never been invoked.

    There is unreachable!() for such situations, and you would hope that:

        if array_access_out_of_bounds { unreachable!(); }
    
    is recognised by the Rust tooling and just ignored. That's effectively the same as SQLite is doing now by not doing the check. But it isn't ignored by the tooling: unreachable!() is reported as a missed line. Then there is the test code coverage including the standard output by default, and you have to use regex's on path names to remove it.
    • steveklabnik 6 hours ago

      A more direct translation of the sqlite strategy here is to use get_unchecked instead of [], and then you get the same behaviors.

      Your example does what [] does already, it’s just a more verbose way of writing the same thing. It’s not the same behavior as sqlite.

  • pella 5 hours ago

    Turso:

    https://algora.io/challenges/turso "Turso is rewriting SQLite in Rust ; Find a bug to win $1,000"

    ------

    - Dec 10, 2024 : "Introducing Limbo: A complete rewrite of SQLite in Rust"

    https://turso.tech/blog/introducing-limbo-a-complete-rewrite...

    - Jan 21, 2025 - "We will rewrite SQLite. And we are going all-in"

    https://turso.tech/blog/we-will-rewrite-sqlite-and-we-are-go...

    - Project: https://github.com/tursodatabase/turso

    Status: "Turso Database is currently under heavy development and is not ready for production use."

    • a-dub 4 hours ago

      sqlite3 has one (apparently this is called "the amalgamation") c source file that is ~265 kloc (!) long with external dependencies on zlib, readline and ncurses. built binaries are libsqlite3.so at 4.8M and sqlite3 at 6.1M.

      turso has 341 rust source files spread across tens of directories and 514 (!) external dependencies that produce (in release mode) 16 libraries and 7 binaries with tursodb at 48M and libturso_sqlite3.so at 36M.

      looks roughly an order of magnitude larger to me. it would be interesting to understand the memory usage characteristics in real-world workloads. these numbers also sort of capture the character of the languages. for extreme portability and memory efficiency, probably hard to beat c and autotools though.

  • 01HNNWZ0MV43FF 5 hours ago

    But if you don't have the bounds checks in machine code, then you don't have bounds checks.

    I suppose SQLite might use a C linter tool that can prove the bounds checks happen at a higher layer, and then elide redundant ones in lower layers, but... C compilers won't do that by default, they'll just write memory-unsafe machine code. Right?

slashdev 5 hours ago

This is ignoring the elephant in the room: SQLite is being rewritten in Rust and it's going quite well. https://github.com/tursodatabase/turso

It has async I/O support on Linux with io_uring, vector support, BEGIN CONCURRENT for improved write throughput using multi-version concurrency control (MVCC), Encryption at rest, incremental computation using DBSP for incremental view maintenance and query subscriptions.

Time will tell, but this may well be the future of SQLite.

  • 3eb7988a1663 4 hours ago

    It should be noted that project has no affiliation with the SQLite project. They just use the name for promotional/aspirational purposes. Which feels incredibly icky.

    Also, this is a VC backed project. Everyone has to eat, but I suspect that Turso will not go out of its way to offer a Public Domain offering or 50 year support in the way that SQLite has.

    • slashdev 3 hours ago

      > They just use the name for promotional/aspirational purposes. Which feels incredibly icky.

      The aim is to be compatible with sqlite, and a drop-in replacement for it, so I think it's fair use.

      > Also, this is a VC backed project. Everyone has to eat, but I suspect that Turso will not go out of its way to offer a Public Domain offering or 50 year support in the way that SQLite has.

      It's MIT license open-source. And unlike sqlite, encourages outside contribution. For this reason, I think it can "win".

  • assimpleaspossi 5 hours ago

    >>SQLite is being rewritten in Rust

    SQLite is NOT being rewritten in Rust!

    >>Turso Database is an in-process SQL database written in Rust, compatible with SQLite.

    • slashdev 3 hours ago

      It's a ground up rewrite. It's not an official rewrite, if that's what you mean. Words are hard.

  • zvmaz 5 hours ago

    In the link you provided, this is what I read: "An in-process SQL database, compatible with SQLite."

    Compatible with SQLite. So it's another database?

    • simonw 5 hours ago

      Yeah, I don't think it even counts as a fork - it's a ground-up re-implementation which is already adding features that go beyond the original.

  • lionkor 5 hours ago

    So they have much worse test coverage than sqlite

  • blibble 5 hours ago

    > Time will tell, but this may well be the future of SQLite.

    turdso is VC funded so will probably be defunct in 2 years

    • slashdev 3 hours ago

      Could also be an outcome. It is MIT open-source though.

    • daxfohl 4 hours ago

      Or, so it's being written mostly by AI.

  • tonyhart7 5 hours ago

    so its sqlite++ since they added bunch of things on top of that

  • metaltyphoon 5 hours ago

    The moment turso becomes stable , SQLite will inevitably fade away with time if they don’t rethink how contributions should be taken. I honestly believe the Linux philosophy of software development will be what catapults turso forward.

firesteelrain 5 hours ago

One thing I found especially interesting is the section at the end about why Rust isn’t used. It leaves open the door and at least is constructive feedback to the Rust community

Havoc 4 hours ago

For a project that is functionally “done” switching doesn’t make sense. Something like kernel code where you know it’ll continue to evolve - there going through the pain may be worth it

morshu9001 3 hours ago

This is what I expected. Rust is the first thing that has been worth considering as a C replacement. C++ wasn't.

jokoon 5 hours ago

I wonder if the hype helps rust being a better language

At this point I wish the creators of the language could talk about what rust is bad at.

  • steveklabnik 5 hours ago

    Folks involved often do! Talking about what’s not great is the only path towards getting better, because you have to identify pain points in order to fix them.

    • estebank 4 hours ago

      I would go as far as saying that 90% of managing the project is properly communicating, discussing and addressing the ways in which Rust sucks. The all-hands in NL earlier this year was wall to wall meetings about how much things suck and what to do about them! I mean this in the best possible way. ^_^

rednafi 4 hours ago

Also, Rust needs a better stdlib. A crate for every little thing is kinda nuts.

One reason I enjoy Go is because of the pragmatic stdlib. On most cases, I can get away without pulling in any 3p deps.

Now of course Go doesn’t work where you can’t tolerate GC pauses and need some sort of FFI. But because of the stdlib and faster compilation, Go somehow feels lighter than Rust.

  • firesteelrain 3 hours ago

    Rust doesn’t really need a better stdlib as much as a broader one, since it is intentionally narrow. Go’s stdlib includes opinions like net/http and templates that Rust leaves to crates. The trade-off is Rust favors stability and portability at the core, while Go favors out-of-the-box ergonomics. Both approaches work, just for different teams.

  • afdbcreid 2 hours ago

    Is Rust's stdlib worse than C's? It's not an argument here.

  • tonyhart7 3 hours ago

    me when I dont know ball:

ternaryoperator 3 hours ago

> Recoding SQLite in Go is unlikely since Go hates assert()

Any idea what this refers to? assert is a macro in C. Is the implication that OP wants the capability of testing conditions and then turning off the tests in a production release? If so, then I think the argument is more that go hates the idea of a preprocessor. Or have I misunderstood the point being made?

next_xibalba 3 hours ago

Aren't SQLite’s bottlenecks primarily io-bound (not CPU)? If so, fopen, fread, or syscalls are the most important to performance and pure language efficiency wouldn't be limiter.

system2 4 hours ago

What's up with SQLite news lately? I feel like I see at least 1-2 posts about it per day.

dgfitz 5 hours ago

> Rust needs to mature a little more, stop changing so fast, and move further toward being old and boring.

Talking about C99, or C++11, and then “oh you need the nightly build of rust” were juxtaposed in such a way that I never felt comfortable banging out “yum install rust” and giving it a go.

  • steveklabnik 5 hours ago

    Other than some operating systems projects, I haven’t run into a “requires nightly” in the wild for years. Most users use the stable releases.

    (There are some decent reasons to use the nightly toolchain in development even if you don’t rely on any unfinished features in your codebase, but that means they build on stable anyway just fine if you prefer.)

    • dgfitz 4 hours ago

      Good to know, maybe I’ll give it a whirl. I’d been under the (mistaken, apparently) impression that if one didn’t update monthly they were going to have a bad time.

      • steveklabnik 4 hours ago

        You may be running into forwards compatibility issues, not backwards compatibility issues, which is what nightly is about.

        The Rust Project releases a new stable compiler every six weeks. Because it is backwards compatible, most people update fairly quickly, as it is virtually always painless. So this may mean, if you don’t update your compiler, you may try out a new package version and it may use features or standard library calls that don’t exist in the version you’re using, because the authors updated regularly. There’s been some developments in Cargo to try and mitigate some of this, but since it’s not what the majority of users do, it’s taken a while and those features landed relatively recently, so they’re not widely adopted yet.

        Nightly features are ones that aren’t properly accepted into the language yet, and so are allowed to break in backwards incompatible ways at any time.

tonyhart7 5 hours ago

because Rust isnt out yet back then????

coolThingsFirst 4 hours ago

I don't want to sound cynical but a lot of it has to deal with the simplicity of the language. It's much harder to find a good Rust engineer than a C one. When all you have is pointers and structs it's much easier to meet the requirements for the role.

plainOldText 7 hours ago

I’d be curious to know what the creators of SQLite would have to say about Zig.

Zig gives the programmer more control than Rust. I think this is one of the reasons why TigerBeetle is written in Zig.

  • metaltyphoon 5 hours ago

    > Zig gives the programmer more control than Rust

    More control over what exactly? Allocations? There is nothing Zig can do that Rust can’t.

    • array_key_first an hour ago

      > More control over what exactly? Allocations? There is nothing Zig can do that Rust can’t.

      I mean yeah, allocations. Allocations are always explicit. Which is not true in C++ or Rust.

      Personally I don't think it's that big of a deal, but it's a thing and maybe some people care enough.

    • Cloudef 5 hours ago

      I think zig generally composes better than rust. With rust you pretty much have to start over if you want reusable / composable code, that is not use the default std. Rust has small crates for every little thing because it doesn't compose well, as well to improve compile times. libc in the default std also is major L.

      • metaltyphoon 5 hours ago

        > I think zig generally composes better than rust.

        I read your response 3 times and I truly don't know what you mean. Mind explaining with a simple example?

        • Cloudef 4 hours ago

          It mainly comes down how the std is designed. Zig has many good building blocks like allocators, and how every function that allocates something takes one. This allows you to reuse the same code for different kind of situations.

          Hash maps in zig std are another great example, where you can use adapter to completely change how the data is stored and accessed while keeping the same API [1]. For example to have map with limited memory bound that automatically truncates itself, in rust you need to either write completely new data structure for this or rely on someone's crate again (indexmap).

          Errors in zig compose also better, in rust I find error handling really annoying. Anyhow makes it better for application development but you shouldn't use it if writing libraries.

          When writing zig I always feel like I can reuse pieces of existing code by combining the building blocks at hand (including freestanding targets!). While in rust I always feel like you need go for the fully tailored solution with its own gotchas, which is ironic considering how many crates there are and how many crates projects depend on vs. typical zig projects that often don't depend on lots of stuff.

          1: https://zig.news/andrewrk/how-to-use-hash-map-contexts-to-sa...

  • Jtsummers 7 hours ago

    > Nearly all systems have the ability to call libraries written in C. This is not true of other implementation languages.

    From section "1.2 Compatibility". How easy is it to embed a library written in Zig in, say, a small embedded system where you may not be using Zig for the rest of the work?

    Also, since you're the submitter, why did you change the title? It's just "Why is SQLite Coded in C", you added the "and not Rust" part.

    • plainOldText 7 hours ago

      The article allocates the last section to explaining why Rust is not a good fit (yet) so I wanted the title to cover that part of the conversation since I believe it is meaningful. It illustrates the tradeoffs in software engineering.