The Case for Rust (in the base system)

If code generator into Rust (or any other language) from, i.e., LLVM IR just like generating native binary codes is possible, rewrite would be realistic.

And by prohibiting UNSAFE blocks, errored out source codes can be considered mutually unsafe, means, Rust is not for the code or real rewrite (refactor) is mandatory to switch to Rust.
According to Amazon research - from: https://aws.amazon.com/blogs/opensource/verify-the-safety-of-the-rust-standard-library/
Today, the Rust standard library comprises roughly 35K functions, with approximately 7.5K unsafe functions, and 3K safe abstractions. The core library has 21K functions, with 7K unsafe functions and 1.7K safe abstractions.
So prohibiting "unsafe" blocks is not possible without banning Rust Core library and Rust Standard library - which is obviously impossible. Same applies to Rust in Linux kernel - all interfaces are plagued by "unsafe" blocks where only comment explains (or rather believes) that it is "actually safe" - but that's not proof.

Just look yourself into latest string source and count all "unsafe" blocks there: https://doc.rust-lang.org/src/alloc/string.rs.html#360

So Rust is no way safer than Perl, Python, Java, Go or any other language with managed memory.
 
Not to pick this nit too much but if you compartmentalize where the unsafe memory management is located, you can then focus on eliminating it vs throwing up your hands and being like "it's impossible, why bother."
 
Not to pick this nit too much but if you compartmentalize where the unsafe memory management is located, you can then focus on eliminating it vs throwing up your hands and being like "it's impossible, why bother."
In many ways yes, but there are so many ways this mechanism falls apart. It would be like putting some unsafe blocks inside malloc and free. Sure, the unsafe code is localized to free but the actual error is in the more complex logic that calls the free. The dangling pointers held by Rust's RAII mechanisms due to the underlying data being stripped are propagated through the entire codebase.
 
I think that's an overgeneralization, considering malloc and free contain the entire set of memory management in C
Absolutely. It was an extreme example. You can go finer grain, but the issue is still there. Memory errors are rarely contained to single sections of code.

Arguably, for C++ you could make it flag up any C function as "unsafe" and you will have achieved similar to what Rust has.
 
Not really. What's "new"?

As per the creator. "operator new and operator delete shouldn’t be in application code"

Just like you don't use new and delete equivalents like std::alloc::alloc() in Rust.

They are there if needed, to interface with legacy codebases (Just like Rust can). But new and delete were never exception safe and even the oldest static analyzers would flag them up as such.

This is different to Java where new is commonly used (and where this mistaken idea probably comes from). Check out a C++ codebase like this and you will see there are no deletes and the only new is placement new (equivalent to Rust's ptr::write). Even in an allocation heavy environment like that JSON library, operator new is correctly avoided. (Though they do use malloc to avoid C++/Rust style construction performance overhead).

This is actually my favorite interview question to candidates. It tells me if they are actually a C++ developer or if they are a .NET/Java developer "trying their hand" at C++. They won't fail the interview just for this... we have loads of Java projects too!
 
Ok, I haven't written C++ using the autopointer or whatever they replaced it with because I thought that was just as deranged (I was right! They got rid of it!) as the people complaining about Java verbosity and decided at least C didn't hide everything in a runtime, but placement new? Nothing on the heap, hunh? Did we toss out RAII while I wasn't paying attention? TBH, this is why I don't take C++ seriously: Never get a new tool, just hold the old tool differently and maybe tack something on to it. I have way more respect for "ok, those ideas were bad and we're breaking from them by making something new."
 
Ok, I haven't written C++ using the autopointer or whatever they replaced it with because I thought that was just as deranged (I was right! They got rid of it!).
It lives on a unique_ptr. Basically auto_ptr with move semantics. You can even typedef/using it. It was a design that was actually pretty good, but now its fixed to be usable in standard containers. std::vector<std::auto_ptr<T> > is invalid due to its simplistic ownership semantics. Of course a std::list<T> is better but can't work with inheritance due to slicing. All of this is solved by Java by putting *everything* on the heap.
as the people complaining about Java verbosity and decided at least C didn't hide everything in a runtime, but placement new? Nothing on the heap, hunh? Did we toss out RAII while I wasn't paying attention?
Placement new allows you to construct into raw memory (both stack or heap). It is mainly for container writers and again, is rarely seen in application code. The equivalent Java (or Rust) to allocate into existing memory is not elegant to say the least.
TBH, this is why I don't take C++ seriously: Never get a new tool, just hold the old tool differently and maybe tack something on to it.
I agree that tacking stuff onto old tools is a good approach. This is precisely why I like C++, Objective-C and Objective-C++. Though C++ isn't really a new tool. It was almost released to consumers at the same time as C.
I have way more respect for "ok, those ideas were bad and we're breaking from them by making something new."
Sometimes a clean break is good. I don't think Rust's approach of binding against C libraries for allmost all of its functionality is sustainable. RedoxOS is where I think it might stand a chance.
 
Personally I'd say my greatest pet peeve with any codebase I deal with is build time.

Which has left me with the view point of:
Bugs are temporary but added compile time is forever.

So the premise of adding extra compile time to preemptively avoid bugs is usually something I run from. I'd rather a project take 20% longer for me to debug and sort through all the bugs in something like minimal C, rather than double my build time by adding layers of abstraction and complex type checking. There is a one-time cost of time to fix the bug. Whereas the added compile from extra preemptive checking and abstraction I have to live with forever.

Even worse, some language features can cause compounding compile time and binary bloat. Such as C++ templates using C++ templates, with types nested in types, and having to duplicate and process it for every variation.

I really hope if any new languages are seriously considered the added compile time, and potential for that compile time to compound non-linearly, is seriously considered.
 
Personally I'd say my greatest pet peeve with any codebase I deal with is build time.

Which has left me with the view point of:
Bugs are temporary but added compile time is forever.

Are you talking more about total compile time (project from scratch) or incremental (one-line change to running)?

I am highly sensitive to one-line change compile time, but total time doesn't bother me.
 
Are you talking more about total compile time (project from scratch) or incremental (one-line change to running)?

I am highly sensitive to one-line change compile time, but total time doesn't bother me.
You seem to have a beefy machine.

But considering other people, aren't there regularly posts here in the forum like “poudriere rust build never finishes since a week”?
 
You seem to have a beefy machine.

But considering other people, aren't there regularly posts here in the forum like “poudriere rust build never finishes since a week”?

To a certain degree I indeed think that people who want to compile the elephant ports should buy a semi-beefy machine (say $1000). I know this isn't possible for everyone, but machines that are cheap or otherwise crippled (some laptops) will naturally lead to high compile times.
 
Personally I'd say my greatest pet peeve with any codebase I deal with is build time.

Which has left me with the view point of:
Bugs are temporary but added compile time is forever.
Not only compile time, but also memory requirements. I frequently have to deal with “professional” C++ code bases, where the compiler crashes with Out-of-Memory errors due to C++-template insanity. The “solution” is then to reduce the number of cores. Absolutely ridiculous.

I never had such problems with C projects.
 
Are you talking more about total compile time (project from scratch) or incremental (one-line change to running)?

I am highly sensitive to one-line change compile time, but total time doesn't bother me.

Both incremental time and build from scratch time.

If you are hacking away by yourself incremental time is of course the much worse offender.

However, in a production environment where CI will clone and do a from scratch build every iteration, potentially on multiple platforms. The from-scratch build time becomes a major chokepoint. I have been in scenarios where the CI iteration time would come to take so long, I honestly believed it was going to make the company fail as every little comment or change request on a PR would mean you'd have to wait another day, to even a week, to make it through CI. Things which a small team could sort out in a day if CI only took an hour or two would start to take an entire month in a bigger department.

I find C++ codebases tend to go this direction. It is a serious problem in the industry I do not see enough people reflect on. We have a good three decades to look back on of big C++ projects to really ask, are they in a good condition today? As I see it, only a big tech corporation with piles of cash to burn could eat the maintenance costs of dealing with something like the Chromium C++ codebase due to how much time it takes to change or fix anything. This should be a red flag to any project which cannot carelessly burn millions on maintenance, to stay far away from any development mentality which produced that circumstance.

I worry Rust codebases will end up in the same place if they get big enough. As Rust already has worse compile time than C++, also has features which can cause compounding compile time, and is flippant about the cost of compile time with the 'Zero Cost' jargon. I had really hoped if any new language came to compete with C++ it'd take very seriously the issue of compile time and process iteration time. It's a lesson we have learned from large C++ projects, but too few seem to give it the recognition it needs. I worry the crowd hyping Rust has not experienced the pain of massive C++ codebases that takes weeks to get any little change through its process. Whereas if they had, compile time would be higher on their priority list.
 
Total compile time really gets to be a pita in huge projects, to th point where the dev team looks like they had met Vlad the impaler. Throwing money at the CI chain is a clear sign of technological debt, fought at the wrong end. I had my battle with the "architects" about this, and they tried to tame the beast with enterprise architect. Given the current status, I would rather put my time into fpc over llvm (not thinking at rust at all). Llvm is the reason I will stop tracing -stable, it needs a rebuild every blooming time.
 
Shouldn't a run through the regression test suite take even longer than a full build?

That shifts things a bit more in favor of the slow-compile, run-fast languages.
 
Big projects tend to be set up in teams and certain rules for check in to trunk. We had this big beautiful C++ mess which had several GB of source code. You make a change, build locally, run the test suite (locally), find it in order. Oh, and reviews by others from the team. After that you were allowed to check in/merge to trunk. Well, in the mean time, somone else had made changes. So you update, fix the problems which were just introduced into your code, made the reviews happen, made the test runs, ... And that is a huge architectural debt, and you can not get out of that hole by throwing money at the CI pipeline, while paying 6 figures to the architects which did not understand how abstraction works in C++. They solved that with templates, not virtual functions or base classes.

I think these guardrail languages are to the benefit of modern programmers, vibe coders, and other unexperienced actors (maybe AI). Holding your hand from school to the retirement home. You fight problems on the highest level, not the lowest. That requires instinct, experience and maybe a few tools. Making things foolproof means fools will do them. AI has a big problem there, it does learn what is presented as "working", but it has no idea what to do with the counterpoints, like "when does this work and when not". That's when you need the hand holding. Junior developers mirror AI here, and vice versa. Maybe this is one of the fermi filters. Our software ecosystem will only tolerate to be a certain distance from the Z80/6502, from those who learned from the base up. Just imagine a mechanical engineer who never held a hammer. Why should we tolerate that? And live in houses what were made by people who never had a single brick in their own hand?
 
Shouldn't a run through the regression test suite take even longer than a full build?

That shifts things a bit more in favor of the slow-compile, run-fast languages.
Not really. You can do the test runs in parallel on a room full of hardware. Building usually has choke points.
 
You split your massive code base into separate crates, to stay in Rust parlance, and iterate those independently. That seems to be how Rust envisions code bases to be designed. My own hobby projects are nowhere near "huge" territory but they pull over 150 external dependency crates routinely. Those compile once on my workstation and that does indeed take a while. Every single line change in my own code after that is done rebuilding in a few seconds. This works so well for me that I split my own code base into privately hosted crates and they, too, only get rebuilt when touched. Build times cycle around faster than I can think.. which may obviously tell you more about my slow brain than it does about Rust, but works for me. When I get tired of all the layers of abstraction my Commodore 64 is still there for some proper Assembly coding though, like a breath of fresh air.
 
You split your massive code base into separate crates, to stay in Rust parlance, and iterate those independently.
And each crates should be independent ports and should assume dynamic linking. But Rust devs would strongly hate the idea, Unixism.
 
Separate, independent FreeBSD ports for each crate is unworkable. I honestly don't care how much it would be preferred or would fit FreeBSD's philosophy better because of the massive amount of rowing against the stream that would be required from a ports maintenance perspective for no tangible benefit. Ruby gems, NPM.. FreeBSD doesn't get to change this because the world at large doesn't listen to us and I'm not in the habit of worrying about things I cannot change.

An application in Rust would pull in its dependencies through cargo and, usually, crates.io because that is how the Rust ecosystem is. That application could be a port in the ports collection. How the application itself gets built is not FreeBSD's problem to solve, it's an application developer and/or port maintainer problem. The port's "make" command spits out an artifact that "make install" puts onto your system and it's done.

Rust in FreeBSD base is a completely different animal. I wouldn't immediately oppose using Rust as a language for use cases that deliver a self-contained binary, although it is a massive lump of infrastructure that (to me) really doesn't have any business existing in FreeBSD's build infrastructure if it's only there to build an alternative to 'sudo' or some such. The 'cargo' dependency manager could be useful though, but I would vehemently object against using crates.io in any way shape or form. If this were up to me at all I'd decree that all of FreeBSD's base code lives in FreeBSD's base repository and nowhere else so it can be managed as a single unit with a single person/entity responsible for its upkeep.
 
Back
Top