276 comments

[ 2.2 ms ] story [ 264 ms ] thread
Guys please make a pizza box Oxide.Computer workstation :)
What is Oxide computer?

I saw the talks, but I still have zero idea of what it is they want to sell.

We will be selling servers.

Here's a thread from last time this came up: https://news.ycombinator.com/item?id=23979042

> We will be selling servers.

Like you, I'm from the generation that grew up treating "computer" as synonymous with "personal computer", i.e. something on a desk or in one's lap. For some reason I can't quite articulate, it saddens me that a new company with "computer" in the name is focusing on those other things called computers in far-away buildings that we can't access. I hope that once Oxide starts making money from servers, it can branch out into workstations. Then, to me at least, it will more fully live up to the name "Oxide Computer". Yes, I know this association is more emotional than logical, but there it is.

One of the things driving things into "the cloud" is because the hardware companies can buy can't compete on performance with the hardware that Google/Amazon/Microsoft/Facebook can make. That drives businesses to move things to the cloud. However some things _can't_ go to the cloud (legal reasons of all sorts for one) and so are stuck with an inferior situation. Assuming you had the money, there's nothing stopping you from putting a server rack in your house. If there was a company selling such hardware, maybe the trend to putting everything on the cloud would change.
I just like Cantrill, he kicks butts and dtrace them afterwards. Great Speaker!
(comment deleted)
Do you mean great shouter?

I enjoy the content of his talks very much, but the constant shouting is very tiring.

{:#x?}

omg!

(comment deleted)
It's a formatting sublanguage based on the one from C#.

In the formatting sublanguage, braces denote a value to be formatted: `format!("{foo}", foo=42)`

Instead of a name you can identify values positionally, counting from zero: `format!("{0}", 42)`

You can omit the identifier entirely and the arguments will likewise be interpreted as positional: `format!("{}", 42)`

To tell the formatter the manner in which you would like to format the value, you can give format specifiers. These are separated from the value's identifier by a colon. An example of a format specifier is `b`, which prints the value in binary: `format!("{foo:b}", foo=42)`

As before, you can leave out the name to refer to the value positionally: `format!("{:b}", 42)`

Other format specifiers are `?`, which tells the formatter to print the "debug" output (i.e. autogenerated output useful for debugging by programmers), `#` which tells the formatter to insert line breaks and indentation for easier reading, and `x` which tells the formatter to print numbers as hex.

> autogenerated output useful for debugging by programmers

Nit: not necessarily autogenerated, we can implement Debug by hand. It's just that, as the name indicates, this is aimed at debugging output rather than the possibly-user-facing output of Display.

Indeed, though it's worth driving home that the salient difference between Debug and Display is that the former, unlike the latter, can be autogenerated via derive (well, okay, I've seen crates that add the ability to derive Display based on doc comments, which is pretty cool: https://github.com/yaahc/displaydoc ).
Right! I've been using Rust for ~2 years now and just found out about the pretty print format.
This is the kind of review I love to see. Not just for languages, everything. In my experience, reviews almost exclusively come while something is still novel to the reviewer, not battle tested, and worse, conflated with whatever situations the reviewer just happens to find themselves in at that period of time.

What a wonderful post to be able to read and not have to wonder how much of it will hold up given a little time.

Of course, since these often take months of up-front effort it’s obvious why they’re not as common :(
It's a shame, though. Content aggregators at least should allow the ones that exist to bubble up.
On the other hand, if you wait too long, you run the risk of being afflicted with the kind of Stockholm syndrome/curse of expertise that explains how bad so much of everything is.

When I start playing with something, once the number of papercuts I'm tracking in my head gets above 2–3, then I crack open a fresh notes.markdown file adjacent to the source repo (if there is one) and start recording all my thoughts in the vein of[1], including everything from outright bugs to opportunities for UI improvement. If the project has reasonable bugtracking infrastructure, I'll file them—or for small projects, I'll email the author along with any patches—but since most projects don't, I mostly don't end up doing anything with them. I've often thought that it would be nice if this exercise of "Let's Critique" became a thing, though. If nothing else, it could provide fuel for folks' blogs that have been lying dormant since that one post from 2017.

1. https://pointersgonewild.com/2019/11/02/they-might-never-tel...

Yes!!! I was looking at exercise equipment this week and badly wanted to find reviews for when people had been using it for years. That’s where 98% of the useful info is.

Otherwise reviews are pointless things like the packaging quality and shipment speed.

You might have missed this[1], earlier this week. Probably doesn't have what you like yet, but is along the lines of what you're wishing for.

1: https://news.ycombinator.com/item?id=24707407

Thank you for sharing! Yes that is definitely touching on a big gap (startup opportunity!!!) that I’ve been seeking. Just a matter of time.
The issue with that is that oftentimes by the time something has been used for years, the manufacturer has discontinued the model, or even worse, kept the same model number and did some cost engineering to make the new version less durable.

I agree with you though that a lot of reviews are useless fluff like shipping speed and packaging, and that there should be a better way to evaluate products.

I was thinking about this today in reference to Elixir. I've noticed there seems to be less of the unalloyed fanboyism, and more realism in people's reported experiences with it now they've had a chance to use it for a few years. Reports still seem to be positive, but more balanced, which I think is the sign of a language ecosystem maturing.

I generally take breathless coverage of how brilliant some new language (or tech stack) is with a large pinch of salt. The foibles and pitfalls of modern languages are often hard to spot until people have code-bases that are at least a couple of years old. I think the good stuff is generally easier to see at first, while the problems (which are often consequences/side-effects of the good aspects) generally take longer to appear.

Programming languages seem to follow a variation of the Gartner Hype Cycle, with the twist that just after you get to the Plateau of Productivity and lots of people are quietly getting stuff done with it everyone starts to declare that "language X is dead/dying".

It's also about using the language/tool in ways that it should be used, was designed to be used.

Elixir is great at what it does, but I wouldn't use it for building a CLI tool or something like that.

Definitely. That's part of my point about understanding the problems and limitations.

After thirty-something years of programming I've seen numerous languages (or model) touted as the one true language that will save us all.

What is the best way to confront this problem? On paper languages like Rust, Elixir/Erlang, and Haskell stand out in non-trivial ways from other languages but as you say they require a considerable investment to evaluate properly. Either you risk years of wasted effort or potentially missing out on a game-changing tool.
Let others evaluate the language for you.

Unless a feature of the language is game-changing for you. This might mean it solves a problem that would be very hard to solve otherwise or it might mean it looks very interesting to you.

Which I think is good advice with anything that requires you to be an early adoptor.

Tech youtubers do it for many products (that they deem need it) - unboxing, impressions, review, 6months on etc.
good article, one of the better ones I've seen around Rust and what is cool about it.

I'd like to know what Oxide is up to...

Their site is somewhat explicit about it?

https://oxide.computer/

Also I can highly recommend their podcast, I can't wait for the next season.

https://oxide.computer/podcast/

Their website says what they intend to do, but not what they're up to lately; the last blog post is from July and is fairly meta (process for discussion, not ex. "we're working on firmware this week"). Similarly, podcast last posted in February.
Sorry if that's a bit thin; more detail on what we're doing and why can be found in a (pre-COVID) talk I gave at Stanford[1]. We're definitely not a Deep Stealth company, but we've also been very busy building; expect many more details over the coming year!

[1] https://www.youtube.com/watch?v=vvZA9n3e5pc

That video is great, it was linked on HN a while ago and I watched the whole thing even though it's not my area at all. Really interesting :)
(comment deleted)
Looks like the honeymoon is still ongoing.
A sign of a good marriage is that you never feel like you’ve come out of honeymoon, so I think they have likely made the right choice :)
> A sign of a good marriage is that you never feel like you’ve come out of honeymoon

Does that happen for some couples?

Apparently some small percentage of couples do experience this. I don't think it's some magical "marriage made in heaven"; my theory is that some small number of people have a superhealthy relationship with their ego, and so don't need to differentiate (which is what causes the honeymoon-leaving), and if you get two of them together, they can stay in the honeymoon state indefinitely.
Yes. Some fight on the honeymoon already.
Honeymoon meets guerilla marketing. After a point the lines between a technical blog post, personal brand building and advertising for one's startup/new project become too blurry...

Makes one long for the days when ads were shown in pop-ups and you could at least close them. And the ad people did warn us this would happen :-)

I think a better analogy here might be Citizen Kane.

From a foreigner's perspective, Citizen Kane is a (very) good movie but really nothing special. I enjoyed Rashomon a lot more. However, Rashomon was clearly inspired by it. To really understand the appeal and significance of CK, you have to compare it to movies before it. The reason CK doesn't amaze many people anymore is because everyone now uses these cinematographic techniques! In similar vein, the first Half Life game was groundbreaking and pioneered new ways of story telling. But if you don't remember earlier games, you may be scratching your head.

Every now and then a programming language comes out that is a gamechanger. Such a language won't get out of fashion unless new programming languages start building upon it. I can't say if Rust is one of them.

I don't have a long career in programming, and I know only a few languages, but I'd say Python is one of the languages that managed to set the bar for others. It's still going strong, but it's no longer turning heads with its usability and clear syntax.

I've jumped on plenty of hype trains of new languages over the last 20 years. Rust is the first one that made we actually worry that I might have to eventually switch back to different language in the future. In addition, it's the first language that doesn't have me use Python for quick shell scripting or small prototypes. It's a pleasure to code in.
it's the first language that doesn't have me use Python for quick shell scripting or small prototypes

How do you define quick? Python has a large standard library and so you don't have to hunt for functionality on crates.io and then download/compile -- I have written scripts faster than that.

If you know that a crate exists then you can simply `cargo add foo` and have it download in the background while you get on with writing your script. If you don't know that it exists then you'll have to find it the first time, but you have that problem with python standard library modules too.

Writing scripts with Rust likely will be slower than Python, but I don't really buy that having functionality in crates is part of that.

If you don't know that it exists then you'll have to find it the first time, but you have that problem with python standard library modules too.

Except that, if its in the standard library, you don't have to choose between multiple implementations. I have written scripts faster than I have chosen dependencies.

(comment deleted)
If I want to make an HTTP request in Python, which module should I use? There is a built in one (more than one I believe), but the official docs link out to a 3rd party module https://docs.python.org/3/library/http.client.html
I think things are beginning to get a bit surreal. People arguing that Rust is a better scripting language than Python and now with one particular poor example in the Python standard library means the chaos of crates.io is a comparable solution in terms of reducing choice.

Rust is a great C++ alternative. But seriously, the community has cult like marketing.

FWIW, I agree with you that Python is better that Rust for scripting (I was not the OP), but finding a crate in Rust is generally a matter of googling "Rust http client" or "Rust regex" and reading the top result. Not exactly hard, and in my experience something that I end up doing in every single language including Python, because using the standard library directly is often not the correct choice.
And there's the Rust cookbook. I view the cookbook as sort of a recommended extended std.
> But seriously, the community has cult like marketing.

What in your opinion makes one language cult-like vs. another that many people like and recommend to others?

Cults generally have a very negative impact on those who are members vs. the leaders. Usually the members of cults are taken advantage of and are only there to support the people at the top.

The Rust community is very far from anything cult-like.

Cults are usually bad for the leaders too.
Yeah, am a Rust beginner but very proficient in Python, and despite having being warned of Rust community's zealotry, I haven't found interacting with them anything but pleasant.

The documentation is great. Various channels to interact with the community have always been polite and helpful.

Heck, one would think that the author of a leading book on the language popping up everywhere to give helpful answers/clarifications would be seen as welcome and not in-your-face-activism.

I honestly can’t remember ever seeing any zealotry (apart from obvious trolls on reddit) but any thread on rust will have at least one person complain about rust zealots. It’s just a meme at this point.
I have a question about the English language here? Is “anything but pleasant” a positive? Doesn’t it mean anything else (like unpleasant, horrible etc), but pleasant?
there's a negation preceding that.
That is correct.

The original poster was saying that generally cults will be rather unpleasant for most mid<->lower level members, but are pleasant for the people at the top (generally by extracting value from those lower-level members, whether it's labor, money, or sexual favors).

This seems a bit counterintuitive, of course - "if it's unpleasant, why the hell wouldn't they leave?". Usually cults have coercive tools that either make it difficult for someone to leave, or manage to brainwash them into believing they would be more unhappy outside of the cult.

The phrase "anything but X" means the opposite of X (e.g. see [1]). So, "anything but pleasant" means "unpleasant". I think the commenter just used it incorrectly.

[1] https://dictionary.cambridge.org/dictionary/english/anything...

Edit: acomar points out that the "haven't" negates what follows, so interpret what I wrote above as "the phrase on its own means not X".

Sorry about the weird phrasing. I did mean that I have always "found it pleasant" dealing with the Rust community.

I'm appalled at myself for the silly manner in which I phrased that. I guess I intended to say: "I have found it nothing but pleasant", but instead ended up tying myself up in knots.

“But” used as a preposition means “except”, so this says “the community isn't anything other than pleasant”.
Rust might become a C++ alternative, but still has some catchup to do with 40 years of ecosystem maturity and this is the kind of stuff that gets overlooked when pitching newer languages.
For quick scripts, it’s really hard to beat python.

For what Rust offers, it is unreasonably effective as a quick scripting language, with one big caveat: Once you’re accustomed to the language and have significant experience with it.

I’ve built and own CLI tools in Rust, used in production, where the alternative language choice was python, and the experience has been way better than I imagined. I expected to trade a ton of developer productivity for the extra speed and safety, but the reality is that it’s not even an integer multiple. Not even close. Again, my expectations were different, but in reality it’s been really pleasant.

My read of the comments here is that Rust is competitive with Python for some scripting tasks from the perspective of someone who knows both. I’m not sure where you get the “arguing that Rust is a better scripting language than Python” or that there’s a “cult like” phenomenon when people share their experiences.
The Python standard library is amazing. A few weeks ago, I wrote a program that provides a SMTP relay, mail storage, and web UI for managing email sequencing. The only dependency that it pulled in was pywin32 so it could run as a windows service; if it ran on a Linux box, there wouldn't be a single dependency.

Not including integration testing, the whole deal was two days of work. If I had to pull in and evaluate external libraries I would have spent two days just working out the details of which libraries to select.

At least for now, I don't think anything can replace Python for prototyping an idea.

> The Python standard library is amazing.

I generally agree, but it has some weird holes. There isn't an OrderedSet, it doesn't have a binary tree like Java's TreeMap, its HTTP client isn't great (people mostly use Requests), and there's a lot still missing from its asyncio library.

> web UI for managing email sequencing

You built a web UI without even using Flask?!

I can only second that. People would say that Python is a lot slower than Rust and I would agree, but the slowest software I've seen in my life is the one that never gets released ;)
I love rust, but Python is still my goto for scripting, small tasks, calculations, etc. It's more convenient for nearly all tasks of that shape.

I remember telling my uni professor about that 15 years ago, but she swore by using C for that purpose. It's what you know I suppose, but if you know both languages, Python is much better suited to the task.

> Python is much better suited to the task.

This is not an objective opinion, but subjective. People generally appreciate different things about different languages, and it’s entirely possible for some who knows both languages to disagree with you here.

For quick CLI tools, my favorite thing about Rust is that it has really high quality command line parsers available in the community, and they are type safe.

I’m not suggesting that your opinion is wrong, only that the way you phrased it implies that many people could come to the same objective opinion, while there’s plenty of evidence that folks pick languages they enjoy and prioritize different things than you might.

There's this political correct thing where people act like there's no objective truth and everything is subjective.

That's just not how reality works, there is usually an objective truth even when we can't agree on what it is. You can use a hammer and a screwdriver for putting screws into drywall, but one tool is objectively better, under most conditions, regardless of your personal opinion.

Python is superior to C and Rust for most kinds of scripting tasks, given equal mastery of both. It has a REPL, it doesn't have a compile time, it has a great batteries included standard library. There are plenty of specific tasks that will be exceptions, but that's my subjective opinion. I also think it's closer to the objective truth - and that people who have a different opinion are simply wrong. I'm not afraid of calling it how I see it. I could be wrong here, but I don't think that's the smart money bet.

I mean, I should probably turn this comment into a blog post, but https://news.ycombinator.com/item?id=22712441

That Python and that Rust are not very far off from each other. Rust is surprisingly good at these tasks for people who already know Rust. It's not as far out as you seem to think.

That being said, I am quite sure that Rust is not going to take over as a scripting language or something. But at the same time, it is not completely ridiculous to write some Rust for these sorts of tasks if you're already comfy, and if the libraries are there.

I shouldn't be surprised to see you defending Rust here :) I do see a lot of similarities between Rust and Python.

I don't agree that it's better than Python for most short scripting tasks - but I will grant your point that it's not completely ridiculous either, not by a long shot.

Honestly, I am surprised; if you go read my old Hacker News comments, you'll see me saying that I don't think Rust will ever make sense for the backend of websites. I have been pleasantly surprised as things have developed.
I don't have anywhere near your level of experience with Rust. But yeah that's been surprising to me too.

I still think I'd rank it behind Go and Python for a typical website backend - but it depends on the project and the team.

The more people involved, the more things the type system will save you from, and the more you benefit from being able to build powerful abstractions - which offsets the relatively higher "tax" on productivity with it.

Rust is one of the better choices for backend web development today, a sentence I also find surprising just to write.

Honestly, probably the biggest thing holding it back for that use case is not the language itself but lack of adoption. It's tougher to hire for, and has a less mature ecosystem. I feel the momentum is there and that will change over the next 5 years or so.

> You can use a hammer and a screwdriver for putting screws into drywall, but one tool is objectively better, under most conditions, regardless of your personal opinion.

This is a poor analogy. Programming languages are used for writing programs. You suggest that Python is objectively superior in one context "scripting" than other programming languages. There are languages that are not cross-platform, that would fit that, there are languages like PL/SQL that are limited to databases, those are not practical for many program development efforts. In this context, we're really talking about two different types of hammers, perhaps one has a claw and the other does not, but they are both fairly portable and can target nearly all the same platforms.

But if Python is objectively better than these other general purpose languages, does that imply that there are areas where Python is not superior to these languages? Would it suggest that folks who've been successful even when choosing Python in those cases objectively made the wrong choice?

> In this context, we're really talking about two different types of hammers, perhaps one has a claw and the other does not, but they are both fairly portable and can target nearly all the same platforms.

It's an analogy, but one tool is going to be faster and easier to use. So let's say a screwdriver vs an electric screwdriver.

> But if Python is objectively better than these other general purpose languages, does that imply that there are areas where Python is not superior to these languages?

Yes. There are a lot of areas where Python is inferior. In fact I'm using Rust right now for a project despite having over 15 years experience with Python. Programming languages are tools and they're better or worse suited to different tasks. There is no one language to rule them all - yet anyway.

> Would it suggest that folks who've been successful even when choosing Python in those cases objectively made the wrong choice?

Yes. That you were successful does not fully validate your decision about choice of programming language. It just means it wasn't that bad. It does not mean it was the optimal choice.

I'm surprised people disagree with anything I said in this comment. It all seems like common sense, bordering on the obvious.
> over 15 years experience with Python.

I wonder how much this has to do with you finding Python to be better suited to quick scripting tasks.

Even for small scripts, I find Python to be fairly clunky to use, and just having simple type checking would speed things up for me considerably.

I think one of the biggest problems with Python is this notion of "good for small scripts / throwaway stuff". It is far too often that a program is given this treatment, and then needs to grow or be reused and maintained later.

Trying to replicate bioinformatics work is a huge PITA because of this type of approach.

Actually, check Oracle Forms and APEX.
The only difference between a 'scripting task' and a 'serious programing task' as far as I can see is what you perceive as the scope of the project as you embark on it.

I have had small 'scripting' tasks that are successful accrue enough feature creep over time and turn into a 10000 line behemoth (as far as quick and dirty scripts go). And at that point, you start hoping you hadn't slapped it together with the haste that you did and miss the easy refactorability that Rust gives you.

Yes. Some time between whipping up a little prototype and getting to 10k lines of code, you may want to reconsider the architecture and language of the solution.

That is not a reason to start off thinking it will get that big, so you have to over engineer it, because the vast majority of scripts don't. You design to the most likely scenario.

I agree that Python is better and easier for quick scripting job.

Every single time my “quick” Python script has turned into something I use for more than a week I say “damn I wish I had written this in Rust”.

Write one to throw away. Nothing wrong with rewriting in rust now that you understand the problem better.
When you say that 1L of distilled water at some temperature weighs 1 kg I'll take it as more or less objective. When somebody says that general purpose language is superior just because it has REPL and no compile time I take it as purely subjective. Some languages/implementation while producing native code have perceptually instantaneous compile time, so here is your REPL. And they scale as the task grow way better then Python.

I think it is just your private /subjective opinion and it is not any better than mine.

I have to believe there's a block of people out there who just assume "nigh-instantaneous compile time" is a bit of a bigfoot.

Or maybe they assume that, if you have that, why wouldn't you make the jump to writing a REPL, since the hard part is done...

Just making some guesses.

No , I would not "make the jump to writing REPL". I was addressing this:

"Python is superior to C and Rust for most kinds of scripting tasks, given equal mastery of both. It has a REPL, it doesn't have a compile time"

To me it makes the impression that you are conflating here, hence my answer about REPL. Technically of course REPL is different from having "no compile time".

In any case I do not really consider opinion about Python being the better one for scripting tasks as anything but subjective.

As we mentioned before, those weren't my opinions, just my guesses about other people's opinions.
OCaml more or less has both. Very fast compile times, but also REPL support.

It however does not have Python's batteries-included standard library. Luckily Opam is starting to make that less of an issue.

Are you saying there isn't a an objective answer in this case? Because I don't agree with that.

Given a specific task and 100 programmers equally skilled in both languages, they will accomplish the task faster in one. There will be a clear and statistically significant answer if one were to do a controlled study. It could be that the result is that they are nearly equal, but that would be a surprising outcome.

So when you say my opinion is the equal of yours, you're just saying you have no idea which is closer to the objective truth so you can't compare them. But fundamentally they are not equal and one opinion will be right and one will be wrong (in this case because it's a boolean outcome).

It is my opinion, it is subjective, but I also am willing to bet it's right. And there is a right and wrong answer here regardless of our ability to know it for sure.

Unless you're writing libraries, Rust feels a lot like Python.

One thing that sticks out in a scripting mindset is the various string types, but I mostly accept that as a small price to pay for doing things correctly (OS strings vs. UTF-8 vs. C strings).

Because of the kinds of things I build with Rust, I've had to write quite a few cargo build scripts (build.rs files), which are very bash/Python script-y in nature. Not once have I wished for a different language!

Can you point me to some open source examples of these? I work in Rust and I cannot for the life of me imagine describing it as "scripty". On the contrary I feel constantly bludgeoned by the type system whenever I have to do something in that realm (e.g., a unit test).
Had you ever used an ML-family language before Rust? I hear lots of excitement about Rust but it seems to mostly be about things that I already have in the languages I was using.
The point is Rust has those features without a VM and no performance sacrifices. Its purpose is a C/C++ replacement.
For some people that's important, sure. But a lot of the people getting excited about Rust seem not to need those things at all; the person I replied to was talking about Python of all things.
Because Rust also brings other benefits like a thriving community, a rich and powerful package management and ease of deployment of solutions. Rust made quite a lot of really good design decisions.
You're still answering a different question from the one I asked.
It is a good answer though: yes many of the exciting features of rust long predate it (and rust never made a secret of it), but rust packages them in a much more convenient and accessible form e.g. I’ve borked Haskell stacks as often as I’ve used it and every time I check back on it I’m supposed to use a different thing, never had that issue with rust.
Yeah, Rust kinda has two crowds getting excited about it:

- low-level programmers looking for safer tools to wrangle big, beastly projects.

- high-level programmers looking over the fence because this is the first low-level language that has a bunch of quality-of-life features that are "table ante" for them considering working in a language (most of them only tangentially related to safety, although the safety's probably a huge leg up for them). One of these features of course is the language getting mainstream and survivable enough that they know there will be a long-running library ecosystem.

Great post, especially for the embedded crowd. I'm looking to start using Rust in FW development but hit a couple pain points.

* First, bit field descriptors is a huge pain - where, in C, you would define an enum for the task, there isn't a real equal in vanilla Rust, other than a litany of constant variables. * Second, the over-reliance on nightly is a tough sell for - having inline asm gated makes it very hard. * Third, while format is great, it's also very heavyweight. Not having (AFAIK) variadic arguments is hard, and there isn't really an equal to printf.

I would love to be proven wrong, because I have an OS to write, and would love to use Rust.

> First, bit field descriptors is a huge pain - where, in C, you would define an enum for the task, there isn't a real equal in vanilla Rust

“A litany of constants” is exactly what your c enum is though.

And you can define a "degenerate" Rust enum with explicit discriminant values:

    enum Foo {
        A = 1,
        B = 2,
        C = 4
    }
They are cast-able to integrals too:

    println!("{}", Foo::C as usize); // prints "4"
Doesn’t work so well for flags however.

> Second, the over-reliance on nightly is a tough sell for - having inline asm gated makes it very hard.

The alternative would be to simply not make the feature available at all until it is done and ready, with even higher risk (as it would have been exercised even less).

As is, if the feature is fine for you as-is you can use it, and if you can't or don't want to use nightly you can go and assist its shepherding to stable (https://github.com/rust-lang/rust/issues/72016)

> while format is great, it's also very heavyweight. Not having (AFAIK) variadic arguments is hard, and there isn't really an equal to printf.

There are no safe Rust-level variadics, but Rust can call C variadic functions, and under RFC 2137 (not stable yet I think) define them as well.

You can assign numeric values to enum variants in Rust too like so:

    enum Field {
        Foo = 0b11111111,
        Bar = 0b10101010,
    }

    fn main() {
        println!("{}", Field::Foo as u8);
        println!("{}", Field::Bar as u8);
    }
There is also the bitflags crate: https://docs.rs/bitflags/1.2.1/bitflags/

For lighter weight formatting there is https://github.com/japaric/ufmt

> You can assign numeric values to enum variants in Rust too

Is this (C-style enums) new?

I swear I looked for it a year or two back, found questions about it, with the answers "use constants".

These aren't really C style enums. These are still sum types.

C-style enums are sugar for defining an integer type alias and a bunch of constants without creating any new types or scope.

Rust enums, even with an assigned value, define a new type that can only be one of the defined values. So this type is not an integer and cannot have a bit pattern that isn't explicitly defined.

Rust calls this feature "C style enums," so while you're right there are differences, it's sort of a term of art in this context.

("style" is supposed to reflect that it's similar, but not the same thing.)

Yeah. I hate it ;).

I already have enough trouble trying to explain to new people the difference between C and Rust enums. The phrase "C style" just confuses things more, IMHO.

Admittedly this may be a failure of communication on my part.

That's fair :)

I don't think the name was super carefully considered, to be honest, it just kinda happened.

C enums in Rust can be declared as:

  enum Foo {
    A=0,
    B=1,
    C=3,
    _UNKNOWN(i32),
  }
However, this cannot be compiled by current Rust compiler.
EDIT: Found it in the changelog. This feature was added in Rust 0.8 (2013-09-26) "Explicit enum discriminants may be given as uints as in enum E { V = 0u }" https://github.com/rust-lang/rust/blob/master/RELEASES.md#ve...

They're referenced as a pre-existing feature in this Jan 2015 RFC [0], so they predate Rust 1.0. I don't know quite how old they are, but I suspect much older than that as this feature is necessary for interfacing with C which has been a high priority for Rust for a long time (particularly driven by the needs of the Servo project in the early years).

[0]: https://rust-lang.github.io/rfcs/0639-discriminant-intrinsic...

> Is this (C-style enums) new?

No.

> I swear I looked for it a year or two back, found questions about it, with the answers "use constants".

Possibly because they were asked / answered in the context of bit flags?

Even degenerate, rust enums are not compatible with C enums because they're still type-safe, you can't create any random value and say "that's a Foo", that'd be UB. So if you want bitflags, you need to use constants.

Thanks. I didn't want bitflags, this was just basically for an enumeration of channels/parameters e.g Foo=0, Bar=1, Baz=2. Ideally I'd like one that was numbered automatically and also offered a way of enumerating the possible values at runtime. I can't remember why I went back to constants in that case.

Another struggle I remember was just getting the max defined value. Again the Rust type is pretty Opaque because it hides the all-powerful discriminated union type. I love the Rust enum type, but I wish Rust also had a first-class dumb enum type, with all the C/C# niceties (bitflags, runtime enumeration, selection of backing field). This seems like quite a different from what the rust enum is.

You probably ran into this stuff not being built-in. You can add it on via a macro pretty easily, except that the "selection of backing field" is built in via the repr attribute. An example of this would be packages like https://docs.rs/enum_derive/0.1.7/enum_derive/

The other stuff isn't built in because it would add a bunch of code you may or may not want to your build, and it's easy enough to opt into. We also could solve that problem, in theory, a few ways, but there just hasn't been a ton of demand for it, so it hasn't been done.

With bitfields, there has been increasing demand lately, so we'll see.

I constantly run into the situation where you make 2 or more constants with a prefix. That always felt like a smell to me - but it might be because in C# it would be.

I'm talking about code that ends up looking like this: https://github.com/retep998/winapi-rs/blob/0.3/src/shared/nt...

You get type safety because you can define the type of constant rather than use some primitive, but there feels like something is something missing (nicer autocompletion, better auto generated documentation, and so on).

I would probably wrap constants with the same prefix in a module, but all that really does is make the naming feel nicer, I guess.
>First, bit field descriptors is a huge pain - where, in C, you would define an enum for the task, there isn't a real equal in vanilla Rust, other than a litany of constant variables.

Have a look at the bitlags crate, I use it a lot for this purpose: https://docs.rs/bitflags/1.2.1/bitflags/

You still have to give the literal value of the field instead of using the auto-incrementing enum but that's how I do it in C as well, I find it too error-prone otherwise. And how do you deal with fields that take up multiple bits anyway?

>Second, the over-reliance on nightly is a tough sell for - having inline asm gated makes it very hard.

I agree 100%. I can understand them prioritizing higher level system programing and taking the time to do asm right, but it does make it a bit of a pain to do bare metal Rust at the moment.

>Third, while format is great, it's also very heavyweight. Not having (AFAIK) variadic arguments is hard, and there isn't really an equal to printf.

What do you have in mind here? format! is strongly typed and a lot more flexible than printf. You can't even print custom structs with printf... Actually even printing standard types like uint32_t and friends require macro soup to work portably.

Variadic arguments are pretty much a no-go for a strongly typed, static language since you would need a lot of trickery to get it to work safely under the hood (hence format! being a macro).

But what use case do you have for printf that can't be implemented with println!/format! and friends?

> But what use case do you have for printf that can't be implemented with println!/format! and friends?

I'm guessing they mean that the format! machinery is rather complex and brings in a lot of code. That it's also somewhat slow is a recurring concern .

Have none of the embedded folks created a specialised version of format! which is not generic, and basically only supports the types and styles which c's printf supports?

edit: there's ufmt though it seems somewhat inactive and I've no idea how good it is: https://github.com/japaric/ufmt

> Optimized for binary size and speed (rather than for compilation time)

> No dynamic dispatch in generated code

There's defmt which I think i think is even better (it implements basically the same thing as I have used in a commercial C++ embedded project for a few years, and was sorely missing any open source equivilent when I was first trying to implement it). formatting strings on an embedded device is pointless and wasteful. Heck, formatting log lines before they are displayed to the user is actively harmful to interpreting them! Defmt basically gives embedded projects structured logging and a substantial bandwidth, cpu, and space overhead gain.

https://ferrous-systems.com/blog/defmt/

defmt looks cool for logging but I'd think there are cases where you want to format strings somehow in order to present them to the user e.g. audio track information or whatnot.
> because I have an OS to write

That sounds awesome. Personal project or commissioned?

> * First, bit field descriptors is a huge pain - where, in C, you would define an enum for the task, there isn't a real equal in vanilla Rust, other than a litany of constant variables.

With my Rust language team hat on: we'd love to have native support for bitfields. I'd invite folks who are interested in that to propose a language MCP ("major change proposal"), which I'd expect to be approved, and then collaborate on a spec for them.

Josh are you able to answer my top-level comment about fixed point numbers?
I probably said this many places before, but I rather leapfrog C and get {u,i}N for all n and #[repr(bitpacked)].
There are two separate problems that'd need solving to handle bitfields:

1) Having uN and possibly iN types, for general-purpose use.

2) Placing such types at specific offsets within a struct.

C only handles the second of those: you can have an N-bit type, but when you extract it it comes out as the wider type you constrain it from. So, `unsigned field:5;` will get read as an `unsigned`, not a `u5`.

Rust could handle both, if appropriate sized types exist. (Const generics might be nice here, to parameterize on the type width.) (1) alone won't solve the problem, without some way to define how those types are packed into the struct.

Rust, and Go, and Julia, and D, and Swift, and what not, should have a shouting and fighting match with one another.

When they are done, they can let me know who won and then I'll take that language a bit more seriously.

In the meantime I'm a humble coder sitting in the corner with Python + C + CUDA (plus some scheme and assembly), doing useless things like AI, robotics, IoT, etc.

(comment deleted)
(comment deleted)
None of them have to "win" for you to be able to use them. In fact, each excels in its own niche.
Wow, thanks for opening my eyes.

Time to clear out the next two years so I can learn half a dozen special snowflake randos that contribue ZERO to the problems and projects I'm working on.

Condensed matter physics is unlikely to contribute anything to the problems and projects you're working on as well, but that doesn't mean it isn't useful or that we shouldn't be studying it. Whether it's something that you're interested in is an entirely separate question. Regardless, shallow dismissals are against the guidelines here, so we don't want to hear about it if you're not interested.
Nobody cares about your problems, nobody cares if you learn a new language or not. The thread is about reflections on using rust - if you don't want to learn/use it fine, but being irritated that others are is just strange.
If they contribute ZERO to the problems and projects you are working on, why would you want to know which one "won"—it will still contribute ZERO to you.
If anyone is wondering if it’s worth the effort to read a comment that’s greyed out to the point that it’s white - IMO it wasn’t. I’d like my time back.
Sometimes they are, particularly when comments from new users or those caught up in a shadowban–so I keep showdead on. But, yes, one must often be aware that they may be grayed out for a good reason.
These languages aren't even try to capture the same market niches. Swift is literally vendor locked. How the heck is it next to open source runs anywhere languages?
Nice. This is Rust for people programming machines of Arduino size.
I disagree with the pleasure of asm macro.

Nothing beats PC / Amiga inline Assembly code blocks / compiler intrisics.

Could you point to an example, or give a more precise thing for me to search for?
The PC / Amiga compilers used to allow for explicit inline syntax as part of the language.

The frontend compiler is intelligent enough to understand Assembly, instead of blindly giving it to the backend, like it always happened on UNIX compilers with their separate phases as processes connected via pipes.

Nowadays they have intrisics which are a mix of specific CPU ones, and others that are general purpose ones.

Then the macro Assemblers that come with them are powerful enough to program almost C like code in Assembly.

Check VC++ inline Assembly, intrisics and MASM.

Borland had similar offerings with Pascal, C, C++ and TASM.

Other PC and also on Amiga, had similar offerings.

That's a huge tradeoff with compiler complexity. Not only can you have issues of syntax incompatibility, but you also have to implement the syntax for every assembly variant for every architecture you support.
Also keep in mind that once Rust stabilizes this implementation of asm, external libraries will be able to build nice wrappers on top of it if they so desire. What Rust seeks to provide here is just a sane platform-independent baseline.
The same syntax issues as the UNIX way, so I don't see the benefits of the UNIX way, other than its traditional simplicity before productivity in developer tools, with strings being copy around in process pipelines as dumb compiler phases.
I always found the Microsoft / Turbo C++ inline assembler syntax clunky, very limiting compared with the GCC version.

With the Microsoft syntax you were generally stuck with having to fix specific registers, and hope the surrounding code was ok working around the asm code and its unstated and excessive constraints.

Whereas with the GCC extended assembly syntax, you can tell the compiler that it has a choice of which registers to use, which memory locations are read from and written to, and many other options that the compiler is free to optimise with.

The GCC version is much better for optimisation. It can even optimise away assembly instructions whose output is stored in a variable that happens to be unused by another part of the program, and select between code using registers or code using inline constants or direct memory operands, depending on expressions that are passed to functions. It also works with "new" instructions that the compiler doesn't know about but the assembler does, or even assembler macros and linker directives that the compiler doesn't know about. The Linux kernel has used all this flexibility to great effect since the beginning.

Anyone with compiler design experience knows that the same is possible with the PC /Amiga syntax, like DMD does, nothing special about GCC's hieroglyphic syntax.
I have plenty of compiler design experience and I don't know that. What I have seen is in line with my comment.

But I'd be happy to discover something new.

Care to show me a real-world, working example of compiler-optimisable assembly inlines with something that isn't using the GCC extension?

If by DMD you mean the Digital Mars D compiler (which is called DMD), then:

No. I checked the online documentation just now for DMD x86 just to be sure. According to that documentation, its inline assembly doesn't provide any of the flexibility that I listed.

You can see that easily by the way DMD requires you to name the exact registers in the inline asm, and the way the operands syntax is fixed as either a register, memory, memory with base and offset etc (the usual Intel things).

But DMD doesn't let you say "pick any suitable operand type". With GCC the compiler will select among possible operand types according to what fits best with the surrounding code. This way it avoids unnecessary loads, stores, register transfers etc. when interleaving C with asm, intrinsics with asm, or even asm with other asm from different inline functions.

You certainly can't do any of the fancy stuff the Linux kernel relies on, with asm directives like '.pushsection/.popsection', memory fault fixup tables, asm goto, inline lock hot paths and cold paths, etc.

If I want the optimizer to play tricks with inline Assembly I will use C instead.

As for the rest, I am more than happy with VC++ inline Assembly and compiler intrinsics (which then VC++ can play register games if that is what you're after), as another example.

The widespread of GCC hieroglyphics inside strings, is an unfortunate state of affairs in what concerns inline Assembly.

Of course, use whatever you prefer.

But the techniques I listed, which Linux kernel (and other software) relies on for performance, can't be done in C, can't be done with compiler intrinsics, and can't be done with basic asm in the style of DMD and MSVC either.

A feature to add new program-specific intrinsics to the compiler would work, but I don't know of any compiler which offers that, and it would probably look like extended asm anyway.

The GCC syntax isn't pretty. But I can't agree that it's inferior unless someone points to a better alternative that achieves similar results.

I've written programs that were portable to both GCC and MSVC, using the inline asm syntax of both compilers. The MSVC version produced slower code, because there was no way to produce the asm I wanted using MSVC.

If you cannot write the Assembly you want there is certainly a problem. /s
:-)

Well it turns out I can't, and neither can anyone else if they are looking for the fastest performance, because the fastest assembly depends on the context it is called from.

I had this problem going all the way back to the 8-bit machines, which is why I took an interest in compilers and dynamic code generation. To get the best :-)

> Nothing beats PC / Amiga inline Assembly code blocks / compiler intrisics.

These are highly architecture-specific. If you care about this, you can implement more idiomatic asm support in a separate crate, that parses some sort of custom syntax and then uses the default asm! feature for implementation.

Inline Assembly is highly architecture-specific anyway.
> Steve is using Windows as his daily driver, in part because of his own personal dedication to keeping Rust multi-platform.

Thanks Steve!

You're welcome!

We have a Windows working group that does far more work than I do; honestly, I mostly am just a visible person who uses Windows, more than an expert or someone who fixes a lot of big problems. I do file bugs and patch things where I can.

Personally I used to think I couldn't develop comfortably on Windows, but Rust's tooling is so integrated under the Cargo umbrella that I've never run into a real issue getting it working there, and I rarely even find myself needing to do "real command-line" stuff while working with Rust. A single tool has it all covered, so I don't really have to write scripts or anything. I'm sure the story is less simple for embedded, but I'm not surprised it's totally doable.
It's not that far off for embedded; Cargo's weaknesses here affect all platforms equally :)
This is a good list of positives. I'm surprised there's no mention of bitfields though.

I like the u32::from_le_bytes and into() and so on, but I feel like Rust would be a perfect match for explicit "u3" types when dealing with low-level protocols.

https://immunant.com/blog/2020/01/bitfields/ and similar articles show some options, but none of them feel as natural (ergonomics wise) or even as "safe" as a C bitfield checked by clang.

bcantrill (or others): am I just missing something here?

No, you're not missing something -- this is an area that I would say is (to use a winter weather term) "unsettled." The Immunant blog entry you pointed to is quite good, and lays out all of the existing solutions and the issues with them. Better solutions are definitely possible here, and I'm confident that we'll see them over time. Especially given the incredible obstacles that Rust has overcome with respect to low-level software (e.g., no_std, asm!), making bitfields more ergonomic seems like a very reasonable aspiration, especially considering how many others see the same problem!
Re-reading the end of that post, I’m reminded that Josh had a talk about potential improvements.

I only return to Rust about once or twice a year (currently) and keep cutting myself on an ergonomics thing like this. But I’ve also seen it improve year over year at a remarkable pace. So I’m hopeful, but also always wondering “huh, am I holding the phone wrong?”.

(I work with bcantrill)

We use https://crates.io/crates/bitfield, and some of our dependencies use https://crates.io/crates/bitflags. They're not perfect, but they get the job done.

Disclaimer: I haven’t used bitflags (but I don’t think it applies for my need).

The nginx example in the above blog post seems like a bitfield! equivalent would be... unpleasant.

For very small structs that are just only wire formats, I might use bitfield!. But encoding/decoding protocol headers (e.g., a VP8 header [1], which has a 19-bit “size” field) or interop with other systems where you’d like some checking a la serde, bitfield! seems more verbose than “fine, I’ll do it myself right here against the u8”.

That is, even if that nginx example had a two-bit field in there, I’d take everything at the end and round up to a u8. Then read/write some of these “by hand”, rather than pollute the struct with lots and lots of macro “noise”.

[1] https://tools.ietf.org/html/rfc6386#section-9.1

Yes, this is what I mean by "it's not perfect", there's totally things that could be better. All I'm saying is that this works out well enough for our particular needs generally, and isn't a giant pain point, so that's probably why it wasn't mentioned.
Be careful with C and bitfields, as they can be a minefield too. First, always use an unsigned integral type for them, and second, be careful with bitfield packing rules -- maybe just use 1-bit fields only even.
I have an (in-progress, but usable) project for generating rust code for parsing and generating these kinds of protocols: https://github.com/mwylde/protogen/tree/to_vec. It supports integers of arbitrary bit sizes up to 64.
Cool!

I was curious to see what you chose to do for representing arbitrary bit width. I didn't see an example / test for something like u19 though.

Your backend compilation seems to generate calls to an arbitrary width [1], but I only see explicit 8/16/32/64s generated or tested [2]. The code definitely seems ready for size != width, and answering some of my question "sizes less than 8 round up to u8, otherwise round up to nearest power of 2" [3].

Either way, it looks like a great start! Your little language seems like it probably has enough in it already for my VP8 example.

[1] https://github.com/mwylde/protogen/blob/f812dd74e5cebe680422...

[2] https://github.com/mwylde/protogen/blob/f812dd74e5cebe680422...

[3] https://github.com/mwylde/protogen/blob/f812dd74e5cebe680422...

Does Rust have first class support for fixed point number formats? If not, is there a proposal for that?
(comment deleted)
Do you mean something like decimal floating-point? No. There are several crates that provide such types, though: https://crates.io/search?q=decimal

We've talked about having support for user-defined literals, so that you could have decimal literals; in the meantime, a macro works for that.

Thanks for the crates search link! It looks like decimal floating point is something used for financial calculations.

Fixed point is where say in a 32 bit word, 16 bits is used for the integer part and 16 bits for the fraction or any combination that you can declare. Usually notated like 16.16 or 16:16. Another format example in 32 bits could be 8.24 and also formats in other word sizes.

I found some crates using 'fixed' as the search term.

https://crates.io/search?page=1&per_page=10&q=fixed%20point

It's been my desire to have a language for embedded to have first class support for fixed point just from the ability to work with them like you would a floating point number and not have to worry about macros.

Ah, got it.

Along the same lines, is there anything that'd be needed to have "first class support" other than literals? If we had user-defined literal formats, so that one of those fixed-point crates could define a format for fixed-point literals, would that suffice?

The arithmetic should either work, or be type checked.

Multiplying a Q8.24 with another Q8.24 makes a Q16.48.

In C that's not the same as the '∗' operator; you'd generally cast both arguments to 64-bit first, and rely on the compiler being smart enough to use a 32x32->64 instruction if available instead of 64x64->64. But even that's ambiguous - is it signed or unsigned widening multiplication?

Adding a Q8.8 to a Q4.12 needs a 4-bit shift before the addition. So does adding a Q5.27 to Q1.31.

The right thing to do is, unfortunately, ambiguous.

E.g. when adding Q5.27 to Q1.31, do you need to keep the full range and precision and end up with Q6.31? Or do you right shift the second argument, ignore overflow, and call it a day with a Q5.27 result that is implemented in C as (uint32_t)(a + (b >> 4)? (Though if it's signed, which it usually is, (b >> 4) is dodgy in C anyway as it's implementation-defined.) If you do ignore overflow, is that a saturating addition (like used for audio/graphics) or wraparound (like in C)?

Really, those decisions depend on what the numbers mean, as well as range and precision assumptions the author may already know are valid for numerical reasons. So maybe there's a case for traits on number types which specify whether they are default-saturating, default-precision-maintaining, default-range-maintaining.

Another operation is to change the representation, either to truncate/round some precision bits, reduce range bits (saturating or assuming), or expand range bits prior to doing some sums (because addition doesn't expand the range bits in real implementations, you have to explicitly do that yourself in advance of adding).

The way I see this done in careful DSP in C or C-like languages is as a series of function or macro calls that specify input and output formats, avoiding operators and the ambiguity they imply.

Worth noting that C does have a draft standard extension for fixed point arithmetic, that ought to address these issues.
Are there any architectures in production today where fractional arithmetic is meaningfully different than emulated block floating point and have an LLVM backend already?

I know there are some TI and ADI arch's with special fixed point data types built into their compilers (which are nonstandard extensions to C/C++, fwiw), but they are unsupported by LLVM last I checked.

I've also heard that those niches are having their lunch eaten by ARM M4/M7 cores which have floating point vector instructions, and you can write Rust to target those today.

> Rust addresses this gap with the same “0b” prefix as found in some non-standard C compiler extensions.

In C++ that’s part of C++/14 standard, well-specified.

> we have u8, u16, u32, u64, etc

It’s indeed nice to have fundamental types like that, but <stdint.h> header is required by the standard since C99, in C++ since C++/11. It provides typedefs like uint32_t and the rest of them, thus the same UX.

> DWARF support

Yeah, but no PDB. Ship a Windows program written in Rust, and when it crashes or hangs on end-user’s PC you’re pretty much screwed. You need WinDBG to analyze these memory dumps written by the OS, and for that you need pdb symbols as opposed to dwarf.

Rust generates PDB files by default when using the MSVC toolchain...
> Yeah, but no PDB

Can you expand on this?

    C:\rust>cargo new demo
         Created binary (application) `demo` package
    
    C:\rust>cd demo
    
    C:\rust\demo>cargo build
       Compiling demo v0.1.0 (C:\rust\demo)
        Finished dev [unoptimized + debuginfo] target(s) in 2.28s
    
    C:\rust\demo>dir target\debug
     Volume in drive C is Windows 10
     Volume Serial Number is B4A6-FEC6
    
     Directory of C:\rust\demo\target\debug
    
    10/11/2020  02:03 PM    <DIR>          .
    10/11/2020  02:03 PM    <DIR>          ..
    10/11/2020  02:03 PM                 0 .cargo-lock
    10/11/2020  02:03 PM    <DIR>          .fingerprint
    10/11/2020  02:03 PM    <DIR>          build
    10/11/2020  02:03 PM                61 demo.d
    10/11/2020  02:03 PM           152,064 demo.exe
    10/11/2020  02:03 PM         1,101,824 demo.pdb
    10/11/2020  02:03 PM    <DIR>          deps
    10/11/2020  02:03 PM    <DIR>          examples
    10/11/2020  02:03 PM    <DIR>          incremental
                   4 File(s)      1,253,949 bytes
                   7 Dir(s)  15,995,387,904 bytes free
`demo.pdb` is readily available.
> It’s indeed nice to have fundamental types like that, but <stdint.h> header is required by the standard since C99. ... It provides typedefs like uint32_t and the rest of them, thus the same UX.

C99 requires stdint.h, but does not require that fixed-width types exist; they're optional. In practice, every architecture you'd care to write C on (amd64, aarch64, ...) has fixed-width types.

I've begun coding with embedded rust, it's actually really refreshing to use a modern toolset & language in an embedded environment
Has there been any news on exporting a lib to be used by an android app ? Last time i checked, it was still painful to generate jni bindings.

I’m dying to find a tech that would let me easily write a shared lib that targets web , android and ios, but so far everything seems very experimental wherever i look. Rust seemed to be the closest, but still a bit raw.

Nothing specific has changed here recently, no.

I believe Cloudflare is doing this with the 1.1.1.1 app; maybe someone who is there will see this and chime in.

We've got a blog post about this coming out soon at FullStory. Been doing this for about a year now.
i'm really looking forward to read about your experience
I find it interesting the article didn't mention compile times at all. Maybe since Oxide mostly works with embedded, they have few dependencies and their compile times aren't very bad? I know my primary complaint after working with the language for about a year is that most projects take over a minute to build. Of course, it doesn't help that I keep moving onto larger projects xD but even small things like cargo-deadlinks and ripgrep take a while.
Funny story, I've actually been working on reducing our compile times lately. We had a conversation about this when I started the work, Brian just doesn't have a ton of sensitivity to this in general. I apparently have more :)

There are details that matter, but on the codebase I work on, the current worst case (before the work I've been doing) means a compile takes a couple of minutes; more like two than five. I'm not sure how other codebases at the company are with regards to this, but I don't think they're super long.

What I've been doing drops it to under thirty seconds in basically all cases.

So yeah, it hasn't been a super pain for us specifically. We'll see as time goes on :)

Can you share approaches you've used to drop compile times? I'm wondering if there's anything beyond avoiding macros and generics.
Honestly, it's stuff that's very specific to "writing a whole operating system in Rust," and so unlikely to be broadly useful. Basically, we were doing a lot of "spurious" re-builds of crates, because we were changing flags between compilations, and with some creativity, we didn't actually need to do that. If you're not building a bunch of things multiple different times in slightly different ways, it's not relevant.

I will say that I recently discovered that putting a bunch of crates into a workspace is inherently slower than compiling them all separately, which is pretty surprising. I haven't dug into the exact reason yet, but it makes 4x the syscalls, so I'm assuming that it's checking every single dep of every single member and that has significant overlap.

https://users.rust-lang.org/t/complex-build-advice/48779?u=s... is probably closest to what I can currently say :)

Quoting from the linked discussion:

> The issue with Makefiles is that well, they're not portable. I'm on Windows, and 99% of this stuff Just Works really really nicely, but that means that "just use Make" isn't a real option. I love that Rust's tooling is so cross-platform, and this is just a final pain point. The problem is hard, but it's mostly about fiddly details.

> I'm trying to figure out how good I can make this without throwing it all out and doing something else. If we never push Cargo's boundaries, it will never grow into being a good fit for these projects.

The fundamental problem with Cargo is that it's not a general-purpose build system (like, say, make). It's a black box with a bunch of hooks for achieving certain common things that the black box itself doesn't handle. As a result, every time you step out of the "supported area", it will be yet another "final pain point" & "mostly about fiddly details".

I agree make is not a good fit for a cross-platform project (nor is Meson, IMO, due to the Python dependency). But there are good (IMO) options in this area that meet your requirements (cross-platform, no external dependencies, etc). I can elaborate if you are interested.

Sure, I'm always about hearing what works for folks. It is unlikely that we will switch away, but I'm always interested!
In your case it would be more like "adding" a make-like tool to tie all the steps together rather than "switching away" from anything.

The tool I have in mind is buid2[1] (full disclosure: I work on the project). In this context you would be using it as a portable (and saner) make replacement (though we do have a Rust module in the works but that is geared more toward multi-language C/C++ and Rust builds).

In fact, if you are interested, I am prepared to put my money where my mouth is and code up a demo/prototype for you (without any expectations that the result will be used).

[1] https://build2.org

Thanks; I’ve heard of build2, and if you’re the one posting about it on /r/cpp, I’ve probably seen your posts there too. I’ll give it a try if I have some time!
Yes, that's me. If/when you give it a try, feel free to ping me[1] with any questions or issues.

[1] boris@build2.org, berium on reddit, boris-kolpackov on internals.rust-lang.

> What I've been doing drops it to under thirty seconds in basically all cases.

Is that for full builds or incremental? 30 seconds for a full build is reasonably fast (for rust, still feels slow IMO) but if that's incremental it sounds _painful_.

Full builds, incremental is a few (like five or less) seconds.
Out of curiosity - what hardware are you using ? I kept hearing this but recently started playing with it and haven't found it limiting probably because I haven't used it enough yet. Still I'm curious if this is a problem top of the line HW setup can alleviate.
I recently updated some Rust code I wrote months ago (~April). In the 6 months since apparently its compile time went down from 6m30s to just around 4mins! I know there's been a focus on improving compile time and it's awesome to see in practise too.
The awesome inline assembly macro doesn't seem to be stable though. Isn't it only available in nightly builds of Rust?
Yes. We are using nightly Rust for this reason.
Have you considered using The Flag That Shall Not Be Named? I find it that it is a reasonable thing to do as long as none of the code that depends on it escapes your private workspace.
I just checked, we use asm and naked_functions.

We haven't considered it, really, and that's mostly just because it well, feels wrong. We're just pinned to a specific nightly for now. It's no biggie.

This is also just for one repo, I should say too; we use stable for everything else. Operating systems stuff on stable Rust will be a glorious day...

A little unrelated - but can we have an update on season 2 of the “On the Metal” podcast?
> A great strength of Rust is its safety — but something I also appreciate about it is the escape hatch offered via unsafe, whereby certain actions are permitted that are otherwise disallowed.

I guess so, but I'd kind of prefer to be able to do everything I want in safe mode.

Sometimes you need to work with pre-written libraries. The Rust compiler is unable to reason about anything on the other side of the FFI boundary.
> I guess so, but I'd kind of prefer to be able to do everything I want in safe mode.

Different people have different needs and want to do different things. It is impossible to satisfy everyone's needs – "do everything I want in safe mode" – both from a practical perspective (the language and the compiler would become incredibly complex and therefore buggy) as well as from a theoretical perspective (you would solve the halting problem, among other impossible feats).

> language and the compiler would become incredibly complex and therefore buggy

Ats[1] isn't in such bad shape. Its type system is much more complex, sure; idiomatic ats proves many interesting programming attributes that rust doesn't. But if you write ats in the same style as rust, the only additional complexity you'll notice is you have to manually drop.

> you would solve the halting problem, among other impossible feats

...what?

I don't see what the halting problem has to do it. Safe rust programs aren't required to halt; nontermination is safe, even if not necessarily desirable (like memory leakage, which is also allowed for the same reason).

1. http://www.ats-lang.org/

> I don't see what the halting problem has to do it.

Is the following code safe?

    function_xyz();
    let p = 0x1234 as *mut u32;
    p.write(5);
It is safe iff function_xyz() does not terminate. To determine whether the code is safe in the general case, the Rust compiler would have to solve the halting problem.

Since that is impossible, the compiler uses a heuristic, which defaults to "not safe". It could use a better heuristic, like "Does function_xyz() contain an infinite loop? If yes, the code is safe." But that's of dubious value.

Treating otherwise unsafe code as safe because nontermination makes it dead doesn't strike me as particularly useful. Is there any other case where knowing the termination status of a function is helpful in proving safety?
> Treating otherwise unsafe code as safe because nontermination makes it dead doesn't strike me as particularly useful.

It doesn't matter whether it's useful or not. What matters is that the compiler can't determine whether it's safe or not.

I find it strange Rust marketing people are insisting the language is safe yet it can't dynamically allocate a byte of memory without some unsafe code.

In languages like C# or Java the whole standard library is written in C# or Java. Somewhere deep inside implementation of new() there's a function call to C malloc() or some equivalent. The important difference, native API surface is much smaller this way. All else being equal, an API with a small surface has better chances to be secure than a large API.

> I find it strange Rust marketing people are insisting the language is safe yet it can't dynamically allocate a byte of memory without some unsafe code. In languages like C# or Java the whole standard library is written in C# or Java. ...

C# has an unsafe feature quite comparable to Rust. Java has its sun.misc.Unsafe module. These approaches are not meaningfully better than what Rust does.

Rust tries to circumvent the _need_ for manual allocation entirely by providing plenty of high level constructs (Box, Vec, Rc, etc.) that you can do to safely and easily do what you might accomplish with manual memory allocation in C
All these constructs are implemented in terms of unsafe code. This makes the unsafe API surface (which, in the context of security, becomes attack surface) very large.

Compare to Java or C#. Vast majority of stuff, including these collections, are implemented on top of memory-safe primitives. Usually (unless explicitly writing unsafe code which most people don’t do), the only attack surface is the VM itself.

The attack surface is much smaller in comparison, both JVM and CLR are very simple from the outside, 202 and 234 instructions, respectively.

The attack surface is well-contained, third-party C# or Java libraries don’t patch the VMs, while unsafe rust is used in many third-party crates not just in the standard library.

Also, these VMs are well-audited (most of the implementations are open source now) and widely used all over the industry, including very security sensitive applications like banks and military.

I'm not using this language because the syntax is really heavy and definitely not my cup of tea. I'm puzzled by the ambitions to market this language for the embedded world. The embedded world is full of electronics engineers that are writing code as part of their job. If experienced developers are finding this language overwhelming, how are you going to convince the electronics guys to adopt it instead of using plain old C? Also in this world all major HALs and SDKs are written in C. The toolchains usually are very fixed, since doing embedded systems is hard...
I am an embedded software dev and Rust would fit my job well, but I see what you are saying. However, embedded is not all for Rust and not all embedded is done by EEs. Systems programming goes from bare metal up to things like browsers and databases...
Rust's type system is complicated for a reason. It makes explicit the reasoning that is necessary to allocate and access memory correctly without reference counting or garbage collection. Sure it is easier to start writing C but I believe it is overall faster to write and debug a Rust program because C requires additional sanitization and fuzzing to catch errors.

To quote Grissom from CSI: I've learned that sometimes you can go faster by going slow ;-)

I don’t know. Rust has all these high level features that also contribute to it’s complexity too. Strip those out and you may have a simpler language.
I think this profession is hard enough as it is. I don't think you need another daily source of annoyance like reading code with a difficult syntax or fighting meaninglessly with the borrow checker. I understand the motivations for this language, but I don't like the tradeoffs on a personal level. Definitely not my cup of tea.
You don't "fight the borrow checker" after a while; rather, you enjoy the fact that it exists. "Difficult syntax" becomes enjoyable as well, and it's all subjective.

> I think this profession is hard enough as it is.

Exactly, I think so too. Don't think I need another source of annoyance like spending days on digging at obscure segfaults and data races caused by logical mutability mistakes.

But you don’t fight meaninglessly with the borrows checker. For me, this was only the first few weeks. Once you know the (simple) borrowing rules, it is rarely a problem anymore. It only rears its head every now and then when you know something is valid, but the borrows checker is not able to infer it.

Another dimension to it is that the borrows checker rules also apply in most other languages if you want to write valid code. They are just not enforced and you have to rely on your own discipline instead (which humans are bad at).

Memory safety errors are a far bigger "annoyance" to the profession than dealing with a slightly more complex (but still quite elegant) syntax or understanding borrowck diagnostics ("fighting with the borrow checker"). It's not even close.

The problem with unsafe programming in the traditional C style (with its heavy reliance on shared, mutable, possibly aliased pointers) is that it's inherently non-compositional: proving safety or correctness of such a piece of code is a 'global' problem that cannot be meaningfully decomposed or modularized. That's why Rust's choice of explicitly restricting these features to "unsafe" blocks feels intuitively right - the "safe" part of Rust is essentially the part that can be worked with in a highly modular way, where safety is checked 'locally' via a type system. Future versions of Rust may well make some currently-unsafe features slightly easier to use, perhaps even more idiomatic in a way that might appeal to C developers, but some inherent constraints will remain.

I think (for this discussion) we should have a more clear definition of embedded.

Yes, ARM processors are used more and more, but there are really A LOT of embedded systems out there, which are still, for example, 8 bit. As an embedded dev, who is using pretty much everything from 8 to 64 bit, the kind of memory safety errors you talk about I have yet to see with on anything based on (say) a 8051 or PIC. On a system without OS and without dynamic memory allocation, the borrow checker does not buy you much. It's a different story with an ARM processor and an OS (real-time or not does not matter).

Of course Rust has a more powerful type system, but my experience is, that the preferences for a C type type system dominate the embedded world. Not because it is better or simpler, but because most embedded devs actually like low level. They are simply not interested in type driven development (yes it's just their personal taste) and its benefits.

Or let me say it like this. I see two kinds of embedded devs:

- Those who abstract way the problem ("It's all just a big char array.", "It's all just ints.", "It's all just data structures").

- Those who abstract away the machine ("It's all just objects.", "It's all just types.").

Right now, my observations tell me that the first group is still dominating. Time will tell if this is going to change.

The borrow checker buys you exactly what proper C programming practice buys you. So if you're already doing it right, you never end up fighting it, since you're already obeying the "single writer XOR multiple readers" principle. It simply checks that you haven't broken what was already best practice.

As an embedded dev one of the things I love about Rust is the ability to use the type system to enforce the machine's invariants. Some register has a bunch of bit fields? Break it up using a struct, and unlike C's struct bitfield notation you don't have to shift the values around every time.

Rust forces you to check all enum variants, not just in switch statements like C (and that only with the -Wswitch-enum or equivalent warning) and disallows any unlisted value (there's no "default" for an enum).

Those things alone probably aren't enough to switch, but as a machine-focused embedded dev they're certainly nice to have.

I think that this is a fair argument. When the mental model is already there, changing it is difficult and the trade-offs needs to be in a very advantage position to justify the change.

But over the time this argument loose fairness in some direction. Today, in 2020, I would feel awful if in my meetings I argued that creating unit tests is meaningless, as this will point bugs in my code that I need to fight with. Or that QA is a bunch of mean people that do not understand how to use my library and only want to point to "bugs" that is more work to me to "fix".

IMHO the borrow checker _is_ this test that I do not want to write, or this QA engineer that exercise the code to find a corner case when I am causing a memory corruption in my not-perfect work.

it helps you by pointing out potential issues and challenges you to really understand what's going on instead of just winging it. how is that meaningless is beyond me. i understand moving fast and breaking things is how many things get done, but it doesn't have to be like that.
> difficult syntax

My approach of learning any language with "difficult syntax" is to treat those as language features rather than a burden.

It is the language bridging the coder to the complexity under the hood (the computer). This comes from Rust's nature of being a low-level PL, and it is really awesome to be able to abstract those minute details so that one can write Rust and "look, it's not that different from JavaScript"

Another analogy would be `gerund` in English. English has the `gerund` feature for its speakers to nounify a verb. Other languages don't have that, some even use the same symbols for both the verb and the noun form.

Both Rust's "difficult syntax" and English's gerund needs only one-time learning session. Once you're fluent on it the sentences come out on their own.

Given that C++ has barely made a dent in some of those domains, after 40 years of trying, any Rust advocacy towards that target market can take a lesson or two from why those engineers are unwilling to move beyond C89 + OEM specific extensions.
The problem is that embedded systems today can range from a 1Mhz µC to a complete PC like a Raspberry Pie. While memory management is important for the latter, the former doesn't like any dynamically allocated memory at all.

Also many processor manufacturers have hundreds of different models with similar but different port mappings. They often supply C-header files which helps making your software compatible with numerous different processor types. So even while Rust has a macro system, it would need to be adapted by those manufacturers or C will likely stay the more convenient choice for the time being.

Please tell me how I can shut off the heap and still use portions of the C++ standard library? You can do that with Rust. C++ just wasn't designed with embedded in mind.
C++ has custom allocators and in-place object construction via placement new. That's even better support than current Rust, which is still limited to a single, global allocator for the entire program.
The problem with C++ is, or was when i worked in embedded 20 years ago, that resources are constrained. Memory is limited, so tight control over call stacks are needed. We had a maximum call stack depth of 7 in our GSM handsets, and with C++ (and everything else object oriented) it is very hard to make that guarantee. Inheritance adds multiple calls that are "not needed".

Most of the embedded platforms of old will be 16 bit, and as soon as somebody upgrades them to 32 bit (or more), the problem will most likely vanish. Then the next problem arises. Most embedded platforms are governed by strict regulations (mobile phones, medical, automotive, etc) and requires thorough testing. Even if you upgrade your hardware (and if the current, cheap, 16 bit hardware works, why bother ?), you do not want the challenge of rewriting 20-30 years of code in a new language.

In many cases you're looking at 30+ years of development by 50-100 developers, and while the code itself probably hasn't grown by a factor 30, chances are that the system evolved from a small system where core business was understood by "everybody" into a behemoth where only a few developers/architects actually understand everything , and everybody else just understands what their little corner does.

Many people mistakenly think embedded means small, which is often far from the truth. I used to make sortation devices, and the total codebase for a single sortation device would often reach 1GB of C source code. Around 750MB was "common code", but the last 250MB would be customer customization.

A GSM handset in the late 90's had about 350MB C source code, with the majority of it being protocols (GSM, Edge, Bluetooh, SMS/EMS/MMS, WAP). The lower level ones of those have mostly been replaced by hardware these days, only to have the UI take up much more code.

It's essentially the same problem that keeps COBOL in this world. Newer and (probably) better languages exist, but COBOL has a massive codebase, and while "edge" systems are easy to replace, at some point you're left with "core business" which has been running as a patchwork of COBOL programs for 50 years. There's no easy way to do it, and you need to rewrite everything.

I learned and used C++ on MS-DOS 5, with the constraints of segmented memory with a maximum of 640 KB.

So I perfectly know what is doable when one actually cares on how to do stuff properly.

And then there are those Jason demos on how to target C64 with C++.

> I used to make sortation devices, and the total codebase for a single sortation device would often reach 1GB of C source code. Around 750MB was "common code", but the last 250MB would be customer customization.

This sounds completely bonkers, aren't you including a bunch of static assets like images or whatever else?

There’s that saying we have:

I dress slowly because I’m in a rush.

Yeah, but I think there is another saying that is still true in 2020:

"Time is money".

;-).

Edit: Corrected typo.

The article and the links it references do a good job of explaining the arguments. A short summary:

* Rust's no_std means you can run bare metal with less memory overhead than even newlib based c

* no_std also makes it easier to port to new platforms, as nonportable parts are isolated out of the std lib

* algebraic data types and in particular enums that can carry disjoint associated data reduce the number of error prone magic constants and casts in your code, as well as catching all missing switch cases

* unsafe makes it very easy for you to audit where data races or memory errors are possible, instead of needing to audit an entire c codebase

* The borrow check makes you work more, but in many cases this is justified by it leading you to a less brittle design

The examples, particularly on cliff's blog post, make pretty convincing arguments oo these points imo.

I also wouldn't discount EEs so much. There's plenty of complexity to Verilog and all the other tools they use.

If you are using no_std isn't that the same as just not having a C standard library? I have been programming in C/C++ for over 25 years in ridiculously restricted contexts--even using it to compile tiny trampolines and the such--and I have no clue what you might mean that Rust could possibly have a smaller runtime library than C's "literally it comes with and uses nothing as the C standard library is nothing more than an optional library that most embedded people don't use".
> If you are using no_std isn't that the same as just not having a C standard library

No. no_std means that all standard library functions that involve allocation aren't available. Things like std::collections::{Vec, HashMap} etc. You have access to std::core (https://doc.rust-lang.org/core/index.html), which is pretty useful.

Technical correction: core is a crate, not a module in the std crate. Your paths will be core::, not std::core::.
The context was with respect to memory overhead, so can you explain this difference with respect to that axis, showing that C with no standard library somehow has higher memory overhead than Rust with no_std? With respect to the actual conversational context, I stand by my comparison.
I think the point is that running no stdlib in C is throwing the baby out with the bathwater.
(comment deleted)

   * unsafe makes it very easy for you to audit where data races or memory errors are possible, instead of needing to audit an entire c codebase
I have seen this argument a couple of times before. But I can't make myself buy it. Because I always have to think about embedded systems in the car industry. Look at this list:

https://betterembsw.blogspot.com/2018/09/potentially-deadly-...

The argument is basically "the possible fail places are easily grepable", right? I said in another comment in this thread (jokingly) "time is money". It seems for the devs in the car industry this saying is of utter most importance.

So how does Rust prevent something like this throughout the code base (and those are BIG code bases):

"LOL. I need to get this done. unsafe { ... } "

it doesn't. if such code passes peer review, it's their problem. you absolutely need buy-in from devs that the borrow checker is there to help you and save time for your future self.
> So how does Rust prevent something like this throughout the code base

In some sense, it doesn't. But in another sense, you can't just throw unsafe around things. Unsafe doesn't turn off checks. Unsafe adds new unchecked constructs. This means you can't have written a bunch of code, run into errors, and just toss unsafe {} around it. You'd have to actually re-write it with unsafe constructs in the first place.

You can very much do that, if you want. But it's not a trivial escape hatch.

I understand the "unsafe" construct on the technical level, but thanks for clarification nevertheless.

My point was that, with "unsafe", Rust provides a technical construct which allows to carry over some negative development styles, possible in the C(++) world, without friction (if wanted). And from the list I linked, there seems to be a lot of momentum for this kind of behaviour in certain industries.

   You'd have to actually re-write it with unsafe constructs in the first place.
This is what I think would happen, and tried to describe. Someone trying to implement a feature, failing with safe mode and resorting to "unsafe" from scratch, just to get it done.

So it stays the way it is, i.e. I can't buy the "possible fail places are easily grepable" argument.

Yes, in theory that could happen. In practice, we don’t see it happening. Doesn’t mean it can’t, but time will tell.
It's a large field. I don't think anyone in the Rust world expects it to make a large dent against embedded C anytime soon - rather a subset of embedded developers who would like to not have to use just C are working on it because they would personally want something "better" for their niches. And as the article describes, Rust has good foundations to be able to fit that role, compared to many other languages.
> If experienced developers are finding this language overwhelming, how are you going to convince the electronics guys to adopt it instead of using plain old C?

Because embedded software is increasingly networked (BLE, TCP/IP, ZigBee, etc.) and you can continue writing your communication stacks in C and having memory corruption security vulnerabilities or you can suck it up and try something else for once.

> Also in this world all major HALs and SDKs are written in C. The toolchains usually are very fixed, since doing embedded systems is hard...

1) The embedded world has effectively converged on ARM. This means that the toolchain is whatever ARM shoves out and HALs and SDKs will comply or get no traction.

It also means that you can use actual, real software tooling (VSCode, Meson, Ninja, etc.) instead of "Yet Another Broken Vendor IDE". It's soooo compelling that I personally can run rings around some vendor teams. To be fair--this is NOT limited to Rust. VSCode and its ecosystem enables even C programmers to be stupidly more productive. However, the embedded Rust folks seem to rattle the VSCode folks cage quite a bit more than just plain embedded C folks--this keeps the VSCode guys quite a bit more honest about cross-platform support.

2) Anything RISC-V is in flux, and folks like Bryan Cantrill are leading the charge so the toolchain will be forced to accommodate more than "just C".

3) Even if Rust isn't the answer, you should root for its tooling to break the C hegemony. If Rust finally forces C tooling to acknowledge that "Hey, just maybe we should think about playing nicely in the sandbox and have some useful API's instead of telling everybody to cope or leave because we're the 500lb gorilla.", the successor to Rust will have a vastly easier time.

See. Not all the problems in embedded are network security risks. If you are evangelizing Rust, please stop trying to lure embedded developers with "networks haxxor buffer overflow" FUD because it's simply not going to work.

For instance, a developer writing the software for the sensors of a forklift has enough to worry about to not crushing the skull of someone passing near it. Edit to add: is not that security bugs are not important, but is not what we (embedded developers) are always chasing or taking away our sleep at night. Embedded is wide enough beyond computer networks.

Please take a look at the room around you. Can you count every little chip in there? Including the one in your keyboard, LED lamps, coffee machine? Are all these ARM? NO. Are all these connected to the network? NO. Do you expect them to work 100% of the time without hiccups? YES, and they probably do without you noticing it.

And they are probably running 1000s of lines of C. That's embedded.

> For instance, a developer writing the software for the sensors of a forklift has enough to worry about to not crushing the skull of someone passing near it.

And you don't think having the compiler check memory usage would be useful in this case? In my mind it means more effort can be put on making sure the logic itself is correct.

Maybe, but what checks would the compiler do on my small embedded memory for a program that processes a sensor and raises a pin? It might sound simple but it's an important core project.

Would the compiler check a write outside the buffer that is filled with sensor data? Is that it? I'm not allocating anything so I cannot double free. The program executes in a main loop so there is no data races (perhaps one if the data buffer is shared with an interrupt, but it's a problem as old as the bible and we already have 1000 libraries with safe circular buffers).

Or is the check done at runtime? Will it waste my cycles?

Is that all I should change my language for?

Would the sensor manufacturer help me if I give them a failing case written in Rust?

Is it worth the risk of compiling on a nightly thing that will change next week? Note that people might get hurt for real.

Damn! Now my MCU/sensor is going NRND. Should I freak out because Rust is still not supported for that new MCU yet, and I should write the thing all over again?

While I may not agree with your opinion, I upvoted you because your position is certainly not uncommon and saw your reply go grey. And that irritates me.

I'm getting really pissed off about people downvoting who have nothing constructive to add to the conversation.

Rather than downvoting, fucking REPLY. A downvote is lazy--it's actually worse than doing nothing on a low-vote thread--it's a sin on the level of turning down the premise when doing improv comedy. An articulated position furthers the conversation and actually represents effort.

When did HN readership become such prissy hothouse flowers? FFS.

(EDIT: I turned down the swearing a bit)

I don't actually disagree with any of what you're saying. My only point was that Rust's safety checks and features are useful for embedded. There are obviously many other considerations when making a decision about what to use on any given project.

I suspect Rust will be a clear win on some subset of projects, and will not be worth it others.

(comment deleted)
> For instance, a developer writing the software for the sensors of a forklift

Industrial is a very poor choice of counterexample. You should have stayed with consumer space counterexamples. Everybody in the industrial setting wants their telemetry and data transmitted to centralized computing whether they know what they are going to do with it or not.

As for sensors, how are those distance sensors connected to the microcontoller? Perhaps a redundant automotive bus with real-time constraints like CAN? CAN often has a fairly decently sized, badly written, vendor supplied communication stack in order to use it.

Is that forklift's sensor telemetry going anywhere? If not, then you're probably going to lose out to someone who does when you sell that forklift to Amazon or WalMart. They probably want to know about where the skulls are (gotta track those lazy humans) more than they want to know about where the forklifts are.

> Are all these ARM? NO.

Actually, they increasingly are. USB-C PD negotiation chips, for example, are basically ARM M3/4 cores with specialized hardware. The cost differential between 8-bit and 32-bit microcontrollers is so low that unless you have extreme volumes, you might as well use the 32-bit one and gain all the infrastructure that provides.

> Are all these connected to the network? NO.

Are you sure? Hotel locks had security vulnerabilities because they had a USB port.

The problem isn't whether I can use the I2C bus on your Cuisinart to break into it--if you used a "standard" driver written in C I probably can. These small system don't have to worry about "secure" simply because they aren't worth breaking into--until some really creative person makes them worth breaking into. (Hey, there's a speaker on that innocuous thing that's loud enough that we can talk to Alexa. YAAAARRRR, Me Mateys!)

For Industry 4.0, yes telemetry is important. But, not all industrial cares about telemetry. In that case, what I have seen, is that all the data is sent to a concentrator that has the network stack. This is often a "high-end" (perhaps Linux based) machine with network access. Is not that every chip in a system is connected to the network. For what Rust matters, I'm really want to see high-level stack written on it, or libraries like libssl. I think that's where Rust should be placed not going any lower (in levels/layers).

Regarding ARM, it depends. It's not just a matter of bits over price. Pretty often the combination of features you want are not available in an ARM chip. For example, long term support, some specialized tool, temperature/power supply range, price, available peripherals, etc. And sometimes you might be required to work on some strange 32-bit CISC from Renesas just because the salesperson took the purchasing manager to dinner somewhere.

And yes, everything is hackable no matter the language you use. If you open the case and cut some PCB traces you might read and inject some data making some device to misbehave. But that's the way it is and I don't see the world falling apart because of this. If it really matters, then (electronically) tamper-proof your case would be my advice.

Again, is my honest opinion and the opinion of many embedded developers I work and know: vulnerability FUD is just noise. I'm just being sincere. Of course if you make locks you have to make your system secure. The other billion of embedded applications might not. And that's it.

> Pretty often the combination of features you want are not available in an ARM chip.

No argument. But this is becoming less and less true since ARM has even become standard in automotive.

> And sometimes you might be required to work on some strange 32-bit CISC from Renesas just because the salesperson took the purchasing manager to dinner somewhere.

HAH! Been there ... screamed about that.

We're probably not as far apart as you think, if I'm just writing 100 lines, I'll just reach for C and be finished in an hour or two.

My problem is that none of my projects ever stop at 100 lines. They evolve and only get bigger. Eventually they adopt a "stack" (CAN, BLE, TCP/IP, etc.) from some manufacturer, and it's all downhill from there.

I need help to manage that explosion of complexity and the torrent of bugs it creates, and C just doesn't provide it. I don't think I've programmed an embedded device smaller than the original PDP that K&R developed C on in probably 10 years--maybe more.

And this includes FDA cleared products. The days of just sitting on an unchanging product for 15 years after getting clearance are gone.

I can understand you. This is the reason, I miss lisp. Why language designers ignore syntax ? Syntax should be CONSISTENT, INTUTIVE and LESS AMBIGUOS (there should be one good way to do thing). As a enduser, I want to focus on solving problem at hand, instead tackling/remembering language syntax/quirks(and new apis).

Let me give a very simple example in golang. Function returning single value and function returing multiple values.

func foo(x int, y int) int {}

func bar(x int, y int) (int, int) {}

Even though below synatx works,

func bar(x int, y int)(int) {}

why there is a additional way to do it by removing parenthesis ?

This looks very simple example. But it breaks consistancy of syntax. Adds 2 rules to remember over what saving 2 keystrokes ? In the age of 100x full stack devs, life really sucks.

About newlines and string literals: why do languages allow newlines in source code to be part of strings? is there some hidden wisdom behind that?

Personally, I would expect that the string

    "the quick brown fox
     jumps over the lazy dog"
Would be like this in runtime:

    "the quick brown fox jumps over the lazy dog"
Whereas this:

    "the quick brown fox\n
     jumps over the lazy dog"
would be like this in runtime:

    "the quick brown fox
     jumps over the lazy dog"
I have same question, it is easy to solve in rich text environment [1]. But it is also possible to solve quotes in quotes. Browser solves it beautifully — we never think how <>& escaped while reading the page, it just works in contenteditable.

    let encoded = this.textContent.replaceAll("\n", "\\n")
                                  .replaceAll('"', '\\"')
    return `"${encoded}"`
[1] http://sergeykish.com/c-multiline-string
The spaces are already significant in strings, so why not other whitespace?

If you try to exclude newlines specifically, it becomes messy when you have to deal with indentation. E.g. how should this parse?

   foo = "this is a
          multiline
          string";
If you simply ignore the newlines, you'll end up with a bunch of spaces. If you start collapsing whitespace, detecting indentation levels etc, parsing becomes a lot more complicated, and harder to explain (which you still need to do, because it won't always "just work").
The newline character plays a very important role in formatting source code: long declarations/statements are usually broken up into several lines of code using hidden newlines. These newlines do not alter the meaning of code.

The same hidden newlines though in a string will alter the string: they will make the string multiline.

So, in order to be more consistent with how code is formatted, I'd prefer hidden newlines in strings to not modify the strings.

Everything inside the quotes alters the string, so it's quite consistent in that sense. And even in a language where whitespace is completely insignificant, it's not insignificant inside a string literal.
I can't believe C binary constant is non standard. It is so easy to solve.

Why can't we extend source transformation? The feature is useful - lisp known for macros, javascript recently got string transformation:

    b = s => parseInt(s, 2)
    b`101010`
    42
Of course this requires changes to the language. Can we solve it with markup [1]?

[1] http://sergeykish.com/c-binary-constants