4 ms·
Embedded doesn't mean "small programs that fit in a head". Some projects I maintain are tens of thousands LoC. Modern microcontrollers are being built with 1 or
by scoutt 5y ago
Embedded doesn't mean "small programs that fit in a head". Some projects I maintain are tens of thousands LoC. Modern microcontrollers are being built with 1 or 2 MB of flash (where a full exFAT FS plus an SDXC driver fits in around 30KB, to give you an idea).
Look, I understand and really appreciate your answer, but I keep thinking these are niceties, and if I were to implement (I don't know) SSL from scratch on desktop/server or a browser as you said, I'll probably consider Rust, because of these niceties.
For the rest, low-level system/kernel/embedded/BSP, I'd prefer what I called RISR in a parent comment. That is, Rust stripped from niceties (traits, async, generics), keeping the language to a minimum with safety as primary objective; and something that hardly updates.
Perhaps it could born as an agreement between embedded/kernel Rust developers, to not got to certain places through certain paths.
Because the more you add, the more complex it becomes, and it will always be difficult to keep everybody happy, test, validate, learn, support and interop with/within different architectures, avoid corner cases, etc. Just for the sake of doing "one-liners" like `json_decode(ungzip(request(addr)))`, which I will never do, because I don't have network access, nor persistent media, nor memory for gzipping, or memory to keep and navigate a JSON structure.
It's like Rust tried to first "convince" javascript/go/haskell programmers, and system developers later, when it should have been the other way around. Because it's super cool to have automatic panics on unwrap() and failed allocations, but the moment Rust has been put to do one of the things it's supposed to be doing (kernel drivers?), the panic thing didn't worked anymore, in April 2021. I'm sure you know what I mean.
- pornel 5y agoI hate that Rust has fallen for the "Linux can't OOM" fallacy too. Fortunately the mistake is only in its stdlib. Rust-the-language doesn't allocate, and kernel/embedded projects turn stdlib off. Panic doesn't have to unwind. It can be a trap instruction or `while(true);`, but in case of an unrecoverable bug it has to stop execution somehow. Rust's initial goal was specifically Servo, a browser engine. It was based on a bunch 80s/90s programming languages, and Ocaml which is a bit Haskell-y, but JS/Go specifically and explicitly were a non-goal[1]. [1]: http://venge.net/graydon/talks/intro-talk-2.pdf http://venge.net/graydon/talks/intro-talk-2.pdf Direct C replacement for embedded programming was Rust's goal early on too. Async is for the JS/Go crowd, but it's a late addition to the language, and it's also designed to work without any runtime at all. It can be used in embedded and kernel code, and for non-network things too. At its core it's representing function's stack as a struct. Fancier things are just libraries built from it. If you want compile-time safety and minimal runtime cost, it's unfortunately impossible to do without a more-complex-than-C type system. There really isn't much you can remove from Rust without either creating loopholes in the safety, or losing features that make its safety practical to use. For example, you can't have a safe set that stores void*. You need HashSet<T>, so that the compiler can track of what type it stores (because T could be a struct with a pointer to the stack, etc.). But then you need to hash and compare the arbitrary T type, and that needs some abstraction over types, which traits provide. "Small Safer C" has been tried at least in Checked-C, Zig, and Cyclone, and from these it's clear the problem has inherent "choose two" trade-off of {runtime type checks, complex type system, safety loopholes}. Programming on a type level is definitely is a very different mindset from what C does, but dismissing it as merely unnecessarily complex is a shallow and inaccurate view IMHO. There is an inherent complexity in writing high-performance safe software. The complexity has to go somewhere. If the language doesn't have tools to with it, then you have to deal with it in the software yourself (like the level of vigilance and tooling that's required to have safe C). Rust is a bigger language, but its toolbox is for reduction of complexity in the software you write. The things you dismiss are not optional nice-to-haves, they are part of the solution, and the pay-off for not having to deal with the complexity in the software, because it's already dealt with in the language.
- scoutt 5y agoYeah, I know I was being dismissive. Sorry. But I feel and understand the pain, too. I know if I have to make a safe function that can operate over any kind of data then I would have to accept a void* (or uint8_t*) and a size, and trust the caller, which at the end of the day is what this is all about. A way to fix it would be to have some sort of generic values and a way to interact with them. I get it. On the other hand, "trusting the caller" is also how the world operates today (like files and sockets) so any improvement is a "nice thing to have" (depending on the degree of complexity it carries). Like: constructors/destructors sound like a good idea! Fast-forward 20 years and then you have the rule of 3, of 5, etc. The line of thought is that if Generics increase my firmware size then I wouldn't use them if possible. If I don't use Generics (if possible), then I probably won't need other things. I definitely don't need async. The language is growing to a height and depth I don't really care. But if you say that there's no escape and there is little to remove and this is the way it is, then I take it for granted. I can only hope there isn't much to add either so I can catch up someday! Perhaps I have to look elsewhere.
- pornel 5y agoBTW, C++ shat the bed for other better-than-C languages, but C++’s complexity and design failures are their own. In Rust you don’t have rule-of-whatever, it won’t let you write a half-assed destructor. There’s one way to initialize a variable.