Hacker Newsnew | past | comments | ask | show | jobs | submit | hannesfur's commentslogin

I am a big fan of the embassy project and it’s a great example of why async Rust is so great: Because this is possible. It works without a heap, is a really low cost abstraction and you can do stuff concurrently on a single core chip (where you can’t just spawn a new “thread”) and you don’t have the complexity of an RTOS. I believe there is a great future for embassy ahead and it’s so great how far the team has come.

I also want to give a shoutout to reqwless (https://github.com/drogue-iot/reqwless) which is a HTTP client for embassy-net that even supports HTTPS!

Rust embedded was really never actually better then C or C++ but embassy for me is a big reason why I now make my buying decision based on how well I can use Rust on the MCU.


If you had to pick a MCU to try this out on, do you have a preference for a devkit to test this with?

STM is popular because their lineup is cheap, offers a lot of features, and the documentation is readily available. The flip side is that their errata is lengthy, the Rust HAL is complex to support lots of different designs under the same product names, the documentation from STM is poorly organized and spread out over a zillion different documents, and Mac compatibility needs a gigantic asterisk. You can also get a BlackPill (get the F411 version with 8MB flash) off of AliExpress for $0.99 from WeAct's official store. Unlike STM's own dev boards (Nucleo) you'll need a separate debug probe. Nucleos that'll give you a lot of breathing room can be had for $10-15.

RP is also cheap and has that pretty sweet programmable GPIO and documentation that everyone seems to love. Adafruit has an RP2040 Feather for $12, RP2350 for $15, or with an ESP32-C6 (RISC-V) for $15. NXP has chips with similarly programmable GPIO but they're not well supported by Rust. The RP's PIO stuff is bonkers and potentially very interesting if you wanted to make random protocol dongles. VGA out? Why not?

Nordic stuff looks pretty sweet (and their Bluetooth support seems well loved) but is generally a bit expensive. Dev boards are available from micro:bit and Adafruit, among others.

I've been working on a HAL for an older Atmel SoC and absolutely loved the documentation. But Atmel stuff is expensive. Quality of the Chinese clones is iffy. I set myself back a bit by bricking my one board but am hoping to have a beta release in a month or so.

More recent Atmel/Microchip stuff (D21, D51, E51) has a HAL that the Embassy folks seem to have overlooked. You can get them on Adafruit boards at varying price points.

Or just pick something unsupported and start writing a HAL. It's a great way to get up close and personal with how everything fits together.

The one thing I wouldn't do is get some high end thing to start with. Teensy's (NXP i.MXRT) pack a lot of punch but even their native Arduino libs don't really let you exploit the power. STM's H7 series as well, they're way too complex to use as a learning tool even if they are fairly cheap.


> The flip side is that their errata is lengthy

Just like security bugs, lengthy errata doesn't mean anything. A popular MCU will have bigger errata sheet because it gets more eyes on it.

>documentation from STM is poorly organized and spread out over a zillion different documents

The spreading out over multiple documents is good organization. You don't want to combine your datasheet, reference manual and appnotes into one.


> lengthy errata doesn't mean anything

In STM32G0 for example, there is "SPIv1" peripheral which has very critical implementation bugs which can get SPI to completely stuck until reset by RCC.

There is very brief mention in STM errata about this, I had to dig up forums and dance up with SWD around this.


Which G0 part is this? Can you point me to one of these forum posts?

Sorry, I was digging on that too much time ago and haven't saved any links. AFAIR, there is permanent busy state in certain conditions when functioning in SPI slave mode, unablility to reset TXFIFO/RXFIFO and some edge case with DMA and TXE/BSY when DMA failed and you don't know how many bytes are in RxFIFO.

Someone's in the Embassy matrix channel currently trying to figure out why the SPI driver is preventing the USB peripheral from enumerating on their G0…

  Just like security bugs, lengthy errata doesn't mean anything. A popular
  MCU will have bigger errata sheet because it gets more eyes on it.
Yeah, no. From all outward appearances STM stuff is basically rushed to market, fix the bugs later. We're talking basic shit like xyz clock input or watchdog straight up doesn't work. More advanced stuff like one of their USB controllers straight up doesn't enumerate with ARM Macs — still not in the errata or marketing materials BTW although the workaround may end up beating you with some other bugs. Or the one family that they had to completely rework the USB peripheral while subtly changing the part numbers. Or yeah no.

> The spreading out over multiple documents is good organization.

No, it's really not. It's things like reading up on a peripheral in the reference manual and then trying to figure out which pins you can use with it. Some vendors will put that in the section with each peripheral, most will include a table within the RM, and STM splits it up into multiple documents — per variant within a family because the families are often loosely related.

None of this stuff is offered up in printed form, they could at least hyperlink it (whether intra- or inter- document).

It's not that surprising really. You've gotta cut costs somewhere.


>rushed to market, fix the bugs later

I've yet to see a MCU vendor ship without bugs. At least with ST, the MCU is very cheap.

>USB controllers straight up doesn't enumerate with ARM Macs

I've seen USB devices struggling to enumerate on Mac/IOS devices before. This feels more like an Apple bug to me considering how they work very well on Linux, Windows and Android.


  I've yet to see a MCU vendor ship without bugs. At least with ST,
  the MCU is very cheap.
Moving the goalposts much? You went from "lengthy errata doesn't mean anything" to "at least it's cheap", which was my point entirely. The STM32 lineup is cheap with a bunch of features, has readily available documentation, and that appeals to a lot of people.

  This feels more like an Apple bug to me considering how they work very
  well on Linux, Windows and Android.
Yep, that's the typical STM fanboi response and part of why I'm not so gung ho on STM products. It just feels… cultish and obnoxious.

Meanwhile I've been using Macs on and off since before USB came around and this is the first USB device I've found that glitches out like that. Given that Apple uses off the shelf USB silicon (TI) and the complaints about STM's older USB FS peripherals I came across I'd fully believe it's an STM problem.

What is entirely STM's fault is that they still market the F7 based devices (ST Link, Nucleo, etc) as being Mac compatible. They've also skipped out on putting that fun little wart into the F7 errata.


I sympathize to some extent but really if popular products work for everybody else but not Mac, that sure seems like Apple ought to make it work even if technically it's not their fault, and I note that you've offered no evidence either way on whose fault this is.

Apple's products being shit in some ways isn't even a weird outlier, the company knows its loyal fans have nowhere else to go.


Nordic nrf series of chips are ubiquitous, cheap, really well documented and have very good support for the Bluetooth side of things in embassy.

If you don't need any of the wireless radio stuff, I think the raspberry pi microcontroller family is also ridiculously well supported in rust and it's possible to get one of the newer raspberry pi microcontroller is complete with ethernet and several megs of flash for not even 10 bucks.


RP2040 is really great experience. You can get a debug probe (either buy or make yourself with another RP2040)

I cant tell you how awesome it is with minimal setup to get

- Full print logging

- Option to attach a debugger

- cargo r will just flash your code and reset the RP2040


probe-rs is amazing. In ARM land it works with pretty much any CMSIS compliant gear, and yeah you get debugging and logging on pretty much anything as a result.

I wish they had smaller modules with wifi (pico w is too large for many of my usecases). That's the only reason I keep using ESP-C*. It's getting better but the esp-rs tooling has a lot of very rough edges.

Same. Non-Espressif manufacturers have been sleeping on Wi-Fi capability. Nordic now has a chip, but I haven't tried it. I have been using an Esp running Esp-Hosted, connected to the main MCU over SPI.

It is a little bit complicated to start and understand how the series ESP-S* works, but as soon you do, everything gets better. It does have Wi-Fi and Bluetooth capabilities and also can be very small. A good example are the Adafruit Qt Py series. I am currently working with the Adafruit Qt Py (ESP-S2) and I am in love to that board. This one, doesn’t have Bluetooth, but the S3 does.

Because of the Xtensa, you need to use a special fork of Rust maintained by Espressif, but worth a try.


You've got boards like the Seeed Studio Xiao with an RP2040, that board is absolutely tiny!

The 2040/2350 ones don't have wireless radio.

Oh.. my brain completely skipped "with wifi" in your comment, my bad.

You had me excited for a second :)

Also espressif RISC V mcu's like the ESP32-C3 and -C6 are fantastic.

Some Nordic MCUs are easy too, specifically nrf52840.

Have fun!


Just got my first esp32-c6 and really excited to start playing with it. The p4 looks like a beast and want to try that out eventually as well. Feels good to be back hacking on embedded again.

I'll second this, Embassy on the ESP32-c6 is great.

I agree. the type safety that it brings to the HAL. it's a like cushion for people entering this space.

never understood what a watchdog is tho...


A watchdog is a piece of hardware that will automatically restart the chip if it detects the code as being stuck. The way it detects this is that you have to poke a register of the watchdog every so often, and if the register hasn't been poked for a certain timeout (usually configurable), the chip is restarted.

Watchdogs exist on MCUs but also on some "proper" computers. The Raspberry Pi has one for example.


>Watchdogs exist on MCUs but also on some "proper" computers

All modern computers have watchdog. You can check your logs

`journalctl -b | grep watchdog`

https://access.redhat.com/articles/7129255


That's a software watchdog. The comment you're replying to is talking about hardware watchdogs.

Yes, but those are done in software

There's generally at least one watchdog device available in most PCs delivered in last decade, but it's not always utilized. Essentially at one point an intel southbridge integrated a basic watchdog on all models, and it started to just... be included.

So these days you can find a variation on the TCO timer watchdog in most PCs, even if the exact implementation varies so we now have a bunch of drivers for the different variants.


Linux doesn't see one on my Ryzen 5600X desktop at least. My Intel Skylake Thinkpad does seem to have two though (iTCO as well as INT3F0D, not sure what that is, but if I interpret the files under /sys correctly it belongs to the LPC/eSPI controller PCIe device, while the TCO watchdog is found under the SMBus PCIe device).

In both cases they do have software watchdogs (NMI based) which relies on a hardware timer triggering an NMI in the kernel. But that relies on the NMI handler still working, which is not as good as a real HW watchdog.


Apparently it depends to a little bit on how the motherboard is designed, theoretically SP5100 watchdog which is part of the CPU logic in recent ryzens, apparently, is supposed to be enabled if the motherboard is designed with IPMI in mind.

For whatever reason, it's enabled on my laptop despite it obviously not having IPMI support :)



mac’s too?

“All CPUs” would probably be 99.9999% accurate. It’s just one of those fundamental functions you want in a processor. Whether it’s exposed in the OS is a different matter.

AMD doesn't have it. I just confirmed by grepping through dmesg and journalctl -b, the only time it appears is due to UPS driver notifications (unrelated).

Cortex-A includes a watchdog so yeah.

You don't need to poke the watchdog! Petting or feeding is fine too.


Maybe stuff has changed a lot in the last year but I didn’t experience that problem so far. For me it was the other way around mostly. Where did you encounter that?

I've had to consistently write my own libraries. HAL for STM32, LoRa support, hardware support for every sensor I use (GPS, IMUs, mag, flash memory etc), ESP-Hosted library, etc. Whenever I design something new or change parts, my assumption is I will have to write my own interface for it. It's not too bad, but is a friction point compared to if I had written the firmware in C or C++.

On the other hand, the rust embedded core tooling including the cargo/rustc/it's target system, probe-rs, defmt, and the PAC project are phenomenal, and make the most important parts one of the lowest-friction embedded workflows around!


That’s fair but when there is an async version of the driver or Hal available it should be pretty straightforward to port it to synchronous, right? Maybe Claude code can even do it with minimal supervision…

Edit: Replace blocking with synchronous


I think that's on a case-by-case basis, but from my own experiences, it's usually easier to start from scratch. A totaled car analogy, where the easier path is not modifying something existing. But it depends. Good pt. I think if the library is documented with datasheet or RM references, things are easier.

(Case in point: An example of the the "It's Async or blocking" meme I mentioned.)


In my experience most drivers are simple enough that there's not a great loss from them being reimplemented in different systems all over the place. They're fundamentally interface code, it makes sense for them to change as on of the sides of the interface changes.

(which leads to one of my embedded hot takes which is that I think striving for a generic HAL is kind of misguided. If you're striving for any form of mechanical sympathy, your HAL is almost certainly specific to at least your framework and probably actually your application)


Interesting thought but you would need a lot of these gasses on the one hand and on the other hand it doesn’t help in working against the greenhouse effect. The greenhouse effect depends on the absolute amount of CO2 in the atmosphere, not the percentage. How much infrared light is absorbed by CO2 primarily depends on the amount of CO2 in the atmosphere.

Maybe they felt the increase in capability is not worth of a bigger version bump. Additionally pre-training isn't as important as it used to be. Most of the advances we see now probably come from the RL stage.


This course is actually mandatory in the first year of the CS undergraduate program here at ETH. I remember it very fondly for its great (and passionate) lecture and the hands on experience building a MIPS cpu in the exercise sessions. Probably the best lecture in my undergraduate.


I fully agree! Can also recommend to everyone to take a similar course or use self-study material on the topic. Understanding the lowest layers makes you a better software engineer, as your mental model of a CPU/PC gets sharper.


These seem like the first features that Rust in Linux bring to the Rust language that are not almost exclusively useful to the kernel. In my perception the focus on bringing features for the kernel has held up development in other parts of the language and the standard library.


As I understand it systems programming is the priority application area for Rust, and there are plenty of projects working on OSs, embedded or other bare-metal cases, as well as interoperability with complex C codebases.

At first glance, these features look quite general to me and not particularly tied to the kernel, they are important utilities for doing this kind of programming in the real world.


What's the story with C interop now with these and related changes? I'm out of the loop.


C interop is excellent and has been for years. The one piece that still needs unstable is defining/exposing varargs functions (support for calling them was stabilized many years ago). You can write almost anything you can write in C in (partly unsafe) Rust, in fact there are projects like c2rust that automate this translation.

These new features are all about making things that the kernel devs need possible in safe Rust. This often requires support for some quite fancy abstractions, some of which cannot be expressed in current stable Rust.


> C interop is excellent and has been for years.

Only if you primarily work with `cargo` and want to interact with C from Rust. The other way around has far less support and `rustc` does not standardize the object generation. This is actively preventing projects like `systemd` to adopt Rust into their project as an example.

https://github.com/systemd/systemd/pull/19598


> Only if you primarily work with `cargo` and want to interact with C from Rust.

In what way(s) does Rust's C interop depend on cargo?

> The other way around has far less support and `rustc` does not standardize the object generation.

I believe in this context the understanding is that you're going to be using `extern "C"` and/or `#[repr(C)]` in your Rust code, which gives you a plain C interface. I think attempting to use "raw" Rust code from other languages is a rare phenomenon, if it's even attempted at all.

> This is actively preventing projects like `systemd` to adopt Rust into their project as an example.

Could you point out specific instances from that thread? From a quick glance I didn't see any obvious instances of someone saying that using Rust from C is problematic.


> In what way(s) does Rust's C interop depend on cargo?

Do rust and cargo allow for multiple interpretations of the same C header file across different objects in the same program? That's how C libraries are often implemented in practice due to preprocessor tricks, though I wish it wasn't normal to do this sort of thing.


Rust and Cargo do not build C programs, so, the answer to that is "no", strictly speaking.

However, some people use cargo's build scripts to build c programs, which then you can link into your Rust program. Support would then depend on whatever the person wrote with the script, which in my experience usually delegates to whatever build system that project uses. So it should work fine.


I would expect so. Rust and Cargo don't consume C header files directly at all. They consume bindings generated by bindgen (or hand written if you prefer). So you could probably generate mulitple bindings if you needed multiple interpretations of a C header.

If the header files are consumed by C code that is then consumed by Rust then you'll have full support for what C supports because it will be compiled by a C compiler.


https://github.com/rust-lang/rust/issues/73632 needs to be addressed and then integrated into meson before systemd could consider adopting rust.


Thanks for the example!

I guess looking at that pedantically that's "just" a tooling issue, rather than an issue with the Rust language itself. That's not really a useful distinction from an end user's perspective, though; it's friction either way, and worth addressing.


I have to disagree here a little bit. Calling C functions from Rust is a very pleasant experience, but the other way around is not so nice. You usually have to manually create types that will unpack rust collections into C compatible structures (think decomposing `Vec` into ptr, len, capacity) & then ensure that memory passed between the two sides is free'd with the appropriate allocator. Even with `cbindgen` taking care of the mindless conversions for you, you still have to put a lot of thought into the API between the two languages.

I am currently working on a fairly involved C & Rust embedded systems project and getting the inter-language interface stable and memory-leak free took a good amount of effort. It probably didn't help that I don't have access to valgrind or gdb on this platform.


I feel this might come down to the scope one has in mind when thinking of the word "interop". I think one can reasonably simultaneously claim that the interop "mechanics" are excellent in that it's generally possible to create a Rust library that quacks like a C library and that basically any C library is usable by Rust code, but the interop "ergonomics" are suboptimal in that (as you say) actually writing the glue code can be a bit of an adventure.


I think that's a fair assessment. To your point `cbindgen` makes the mechanics of the whole thing painless & linking was trivial. That's worth a lot especially when compared to other languages.


Cool, thanks for the clarification


Calling C code from Rust? Pretty nice.

Writing Rust code to be called from C (but within the same application)? Doable but somewhat painful.

Writing Rust code to act like a C shared library? Quite painful and some pretty important features are missing (proper symbol versioning support being the most obvious one). Theoretically doable if you're willing to compromise.

There's also some aspects of FFI-safety that are very subtle and easy to mess up:

  * #[repr(C)] enums still have the same requirements as Rust enums and so C callers can easily trigger UB, so you need to use something like open_enum. Thankfully cbindgen is too dumb to know that #[open_enum] is a proc macro and produces a non-enum type.
  * Before io_safety in Rust 1.63, dealing with file descriptors from C without accidentally closing them was horrific (though this was a wider problem in Rust). BorrowedFd is quite nice -- though Rustix will panic if you use negative fds and so you need to add validation and your own type in practice. However, #[repr(transparent)] is very nice for this.
  * Lots of reading about unsafe Rust is necessary when doing most non-trivial things with C FFI.
  * You need to make use of a lot of compiler internals, build scripts, and other magic to get the output you want.
  * Tools like cargo-c and cbindgen are nice and probably work great for 80% of projects, but the 20% really suffer from no useful tooling. I haven't tried to use rustc directly to work around some of the remaining issues, but I suspect it'd be even more painful.
I would say that the C interop with Rust is pretty good but it has lots of room for improvement and it feels like very few resources have been spent on it after they got the core stuff working.

Source: I've been writing a Rust library intended to be used primarily via C FFI and run into a lot of issues...


Thanks for the info, I've been wanting to use Rust in a project with a lot of FFI going both Rust <-> C ways. Still sounds like it's a bit hairy.


It's C++ that is problematic, C has been easy for years


Are the kernel-related changes applicable to C++ interop? Honest question, I don't know.


The kernel doesn't use any C++, so no more than incidentally.

There is some C++/rust interop in the past that I've worked on that would have enjoyed the arbitrary self types feature, but not particularly because of the C++ part of the equation. In fact I think if it had been a pure rust project it would also have enjoyed that feature just as much so... eh... take it for what little it's worth I guess.


There are a lot of features being added for kernel/firmware development, they're just not on everyone's radar.

Philopp has been a particular force for change in this area.


I see Rust's place on low level systems programming, for everything else on userspace compiled managed languages are a much better option, systems following an architecture like Self, Inferno or Android, so I don't see a big deal with these efforts focusing on low level C like capabilities.


> for everything else on userspace compiled managed languages are a much better option

As someone who's written a number of userspace applications in many languages as well as embedded firmwares running on bare metal, Rust is a rare gem that excels at both.


Only if those userspace applications are headless, Rust exceling at GUIs is a bit of a strech.


Well https://github.com/timschmidt/egui-rad-builder has come together rather well in the last week of hacking, if I say so myself. I think building a similar app with QT, for example, would have been significantly more challenging.

I'm particularly fond of how easy it was to make all the controls live in the editor, and editable with changes appearing immediately. imgui would probably provide a similar experience, but I find C++ much more of a pain to work with than Rust.


Regarding Rust GUI framework, there is also Slint https://slint.dev

(Disclaimer: I'm one of the Slint developers.)


I looked at Slint a couple years ago when I was evaluating UI toolkits. Looks slick! The only thing that turned me off was needing an additional DSL to define UIs. Trying to learn fewer languages, more deeply, these days. Is it possible to use Slint without the DSL?


Slint does require using its DSL to define UIs, but I'd argue it's not really like learning a whole new language. It's not harder than learning the API surface of any other GUI framework.

I actually wrote a blog post about this exact topic, since it's a common question: https://slint.dev/blog/domain-specific-language-vs-imperativ...


I don't think the DSL is any good. It looks weird (like a mix of CSS and classes), and it has a side effect of locking the user to a specific product.

In your article, you mention that an imperative code in Rust looks more complicated, but this can be fixed by adding an "object tree" syntax to Rust, that allows creating trees of objects and link them like this:

    VBox margin=10:
        Label text=label_text 
        Button label="OK" onclick=on_ok_clicked
This syntax could be used not only for UI, but for describing configuration, database tables and many other things. I think it would be better solution than a proprietary language.

Also I think it would be better if GUI could be drawn in the editor, it would allow to use lower paid developers without expensive computer science education for making UI.


I appreciate the answer, and you taking time to write up your thoughts on it. Your point about the GUI builder working with the DSL is noted. In the egui RAD builder, I am manipulating structs which describe the UI (and which can be exported / imported as JSON) prior to code generation, which amounts to something similar. I still feel I have to context switch less, the back-and-forth is of more concern to me than learning an additional language.

That said, great work! There's plenty of room in the language for more than one solution!


That’s a compelling post. You drew me in by calling SQL a DSL. You’re right, but if you asked me to list the DSLs I use regularly I never would have thought of SQL until now. My thinking was too uptight because I didn’t consider the “domain” in DSL could be something as big as querying structured data. That makes me wonder if Rust is a DSL for the domain of general computing (obviously not in the usual intended meaning of DSL).

Like the person you’re replying to, I am generally averse to DSLs where the domain is a single project because I associate them with previous bad experiences where I spent time learning only to find it totally misses the mark. There’s also the issue of software where I’m the sole maintainer and look at it rarely. If it’s the only place I use Slint, then I’m going to be worried that I need to relearn the DSL in three months when I want to tweak the UI. Although you can probably say the same about any non-trivial framework’s API whether or not it uses a DSL.

All that said, I’ll be a bit more open to DSLs after reading your post, and if I ever need to write a GUI in Rust I’ll give Slint a shot (although that seems unlikely since I don’t typically write Rust or GUIs).



God forbid a company plays the GPL rules fair and square...


Even FSF makes their central libraries LGPL not GPL.


How does it handle localization and assistive technologies, UI/UX tooling for designers, 3rd party component ecosystem?


egui works with AccessKit to provide accessibility support. I haven't added anything explicitly to the RAD builder for it yet. Great idea!


But that’s no longer the choice you need to make. Ubuntu themselves have said for a couple of years now that every new GUI app they make natively for Linux is going to be Flutter and dedicated a bunch of engineers to the project to make sure it’s a first class citizen.

Beyond that, Dart / Futter are truly an absolute pleasure to use for that use case.


Yeah, I do not know Dart / Flutter much, but if I had to choose, I would either pick that, or wxWidgets, or even Tcl/Tk, but not Rust.


Sounds great for the Dart people. But unrelated to correcting misinformation about Rust. I'm not opposed to whatever language folks want to use. Just out here hacking in Rust because it suits my particular needs. And finding that it's enjoyable to hack GUIs as well as firmwares in.


No I get all that, but to the parent comments point however, there’s no way in hell I would ever pretend for a moment that one is as straightforward as the other and it’s no longer a choice between Rust and C++ both of which add a lot of complexity to a scenario where it offers very little benefit.


Over the years, I've found that the complexity is there whether or not it's been papered over by a runtime. It's wonderful to forget about, until it's not. Some applications may never run into the limitations imposed by abstracting it away, but others run into them quickly.

"There ain't no such thing as a free lunch" as the saying goes.


To which the counter argument I guess would be.. there’s no sense in trying to solve for some abstract future set of problems that the vast majority of people are never going to have ahead of time on the off chance you’re one of them.

That too requires a substantial investment of time and resources.

I think in a more pragmatic sense too that you can form a very good understanding on if you’re going to have weird special requirements just from looking at what others have done with the same tools in similar situations before you.


> there’s no sense in trying to solve for some abstract future set of problems that the vast majority of people are never going to have

> That too requires a substantial investment of time and resources.

The discussion has gotten to be pretty abstract at this point. To get back to concrete examples, the egui RAD builder I've been hacking on worked on day 1, first commit. It's been a joy to put together, and no more difficult than building GUI apps with any other toolkit I've worked with. Which causes me to question your statements about additional complexity. You can dig deep and do dark magic with Rust if you want, but you can also treat it like any high level language and get things done quickly. That's part of what makes it a rare gem to me.

Some folks don't like dealing with strict types, or with the borrow checker, but I find that the errors they illuminate for me would have been similarly serious in other languages which lacked the tooling to highlight them. Which adds to my appreciation of Rust.


One week of hacking makes every library look good, but have you shipped actual product that other people widely use with Rust GUI yet? What was the experience there and - most importantly - what were the downsides?


I've been working with egui for a couple years. Written maybe a dozen applications with it doing various things from image manipulation to 3D graphics. As I've said elsewhere in the thread, I haven't run into anything I wasn't able to accomplish with it.

Immediate mode has it's detractors, but in practice I've found it remarkably flexible, the resulting code relatively clean, and egui gets out of the way when I want to do something like blit fast graphics to a memory mapped area of the screen. Responses have been positive.


> Rust exceling at GUIs is a bit of a strech.

BTW, this happens to almost all languages. Which ACTUAL good GUIs toolkits exist? And which ACTUAL languages HAVE good integration or implementation of them?

A good GUI kit AND integration is a bigger task than do a Os or a RDBMS. (And neither are many good languages for RDBMS)


Delphi, VB, Java, Kotlin, Dart, C#, VB.NET, Swift, Objective-C.

All of the above also have great ORM libraries and RDBMS standard driver APIs, as doing data entry applications is a common enterprise GUI workflow.


Well if that is what you call good from ORM (I agree Delphi for GUI, the others not so much).

A truly good one? FoxPro. Is very hard to know if you don't have exposure to what should be.


Depends on your definition of good.

I think Swift (and even ObjC) is perfect for AppKit & UIKit. I think those frameworks are pretty good and I like using them. Languages have great integration, Swift literally made around them. Those toolkits have great integrations with the macOS.

I find C# a pretty nice language for GUI, I assume it has good (maybe not great) integration with at least one of MS GUI toolkits.

I find Rust good for GUI, but right now story is meh. Wrapper style frameworks always suffer from Rust not being whatever it wraps. Pure Rust framework miss a lot of features compared to wrapper frameworks.


> Rust exceling at GUIs is a bit of a strech.

I strongly agree with this. In particular the Rust GUI libraries I've looked at have text layout / rendering that is nowhere near what should be considered adequate today (imo).

For example egui:

- It doesn't do any bidi reordering.

- It also doesn't do any font fallback so even if you didn't need bidi you can't render many languages without first acquiring an appropriate font somehow.

- Complex shaping is nowhere to be seen either.

- egui's italics look really terrible and I'm not sure why since I can't believe even synthesized ones have to look that bad.

CSS has been doing this for years and it's been doing it very well. So I am kind of disappointed that we don't have equally powerful tools in the general Rust ecosystem. Even just considering text layout / rendering libraries, only `cosmic-text` has an API that is somewhat in the right direction[1], but even it fails simply because I don't see a way to insert a button (block element) in-between the text[2].

Note that I'm not just hating on egui here, egui is amazing. Afaict it is the most complete GUI library for Rust and it's great to be able to make GUIs this easily. However I can't just not point out that it is, in fact, not perfect and doesn't truly "excel" at GUIs.

Also I have no idea how inline layout looks in other established GUI libraries like GTK and Qt so maybe I'm complaining about something that is not available most places outside a browser. If anyone knows, it would be interesting to learn how well they compare here.

[1] CSS inline layout is so complex that even this is a decent achievement, since it is not reasonable to expect most CSS features out of new Rust libraries with a significant time disadvantage.

[2] This is non-trivial because bidi reordering should happen on the whole paragraph not only on both sides of the button, so the inline layout API must handle non-text blocks in text.


This is a detail oriented list of real issues, which is wonderful! ChatGPT found open issues in the egui Github for each of your problems, so they're known about and being worked on.

However, it seems like most of the other UI toolkits discussed here, even in other languages, suffer similar issues. Which points to the difficulty of the problems. Consequently, I don't have any problem praising egui and Rust alongside. They're great! And even great can always get better! :)


Sure, but that's true of basically every language except maybe C++, C#, Javascript/Typescript and Dart.

GUIs are incredibly hard and most languages never get high quality GUI libraries. Rust is still pretty young and a ton of people are working on the problem so that will definitely change.


I wouldn't say it's bad at GUIs either. There are some nice libraries like Iced and Slint. Some even have good accessibility support like egui.

There is a full-fledged DE written in Rust that uses Iced: https://en.wikipedia.org/wiki/COSMIC_(desktop_environment)


Indeed. Last I knew all the Rust UI libraries were declarative and/or immediate mode, both of which have their place but I’m not convinced that they’re suitable in all situations. Sometimes you need a boring “old style” imperative UI framework with deep toolbox of capable widgets (think AppKit, win32, etc), but that’s notably absent in the Rust world.


https://www.gpui.rs/ is a relatively new entrant which is described as "hybrid immediate and retained mode". Maybe worth checking out for your use cases.

Immediate mode was certainly a different paradigm to wrap my head around, but so far I haven't found anything I couldn't accomplish with egui, including some fairly complex applications like https://timschmidt.github.io/alumina-interface/


How far from "old style" is Slint?


From a quick glance, about as far as the other Rust toolkits. Looks declarative with with a relatively small number of more basic widgets (a lot of custom widget code is necessary), as opposed to e.g. AppKit which is imperative and comes with a great number of rich widgets that are ready to use out of the box.


The GTK bindings are fine.


> Rust is a rare gem that excels at both.

This can be true but it can still be the case that a managed language is even better at one of them.


This is not the view everyone holds. For an example of work in the opposite direction see https://dioxus.notion.site/Dioxus-Labs-High-level-Rust-5fe1f....


> for everything else on userspace compiled managed languages are a much better option

Except for thread safety.


Fearless concurrency, is only fearless for a very fine grained version of it.

In memory resources shared among threads.

Turns out threads also may share resources like out-of-process files, memory mapped regions, shared memory, databases, distributed transactions,.... where the Send and Sync traits is of no help.

Also you happen to forget Haskell has a Software Transactional Memory, and Swift also has similar protocols since version 6, and effects are a thing in OCaml, Scala, Koka, while languages like Dafny, Koka and Idris also provide similar capabilities via proofs.


That's why everybody who cares about OS safety should invest into capability-based operating systems. They take the concept of Send and Sync and implement at the runtime of the entire computer.


> for everything else on userspace compiled managed languages are a much better option

That might be true if you're developing a pure application [1], but not if you're writing a library. Have fun integrating a C# library in a Java program, a Java library in a C# program, or either of those in a Python, Node, C, C++, or Rust program. There's something to be said for not requiring a runtime.

[1] Unless you care about easy parallelization with statically guaranteed thread-safety. But hey, who needs this in the age of multicore CPUs?


OS IPC exists for a reason, aren't microservices all the rage nowadays, and Plan 9 rules?


> OS IPC exists for a reason

Message-passing IPC is much, much slower and less efficient than shared-memory communication, and inter-process IPC (both message-passing and shared-memory) is much less convenient than intra-process multi-threading. Rust is the only mainstream language, managed or otherwise, which enables safe and efficient multi-threading.


Not at all, because as I explain on another sibiling answer, it is only safe if we cut down the use cases to a very specific one that helps to sell that narrative.


This one?

> Turns out threads also may share resources like out-of-process files, memory mapped regions, shared memory, databases, distributed transactions

For multi-threaded parallelization,

    - out-of-process files
    - databases
    - distributed transactions
aren't really relevant, and Rust directly helps with the other two aspects:

    - memory mapped regions
    - shared memory
In practice, your "very specific" aspect is the most important one, and the hardest to get right without Rust's Send and Sync traits and their automatic enforcement.


Who gets to say what is relevant is the architect driving the project implementation.

> aren't really relevant, and Rust directly helps with the other two aspects:

Not at all, because Rust code has nothing to say about what other processes do to those resources, the only thing you can do is wrap accesses in a unsafe code block and hope for the best, that nothing was corrupted.


I think you're confusing concurrency with parallelism. I've been talking about parallelization since my first comment in this thread. There's some overlap, yes, but the aspects you listed have typically very little to do with parallelization, which is why I called them "[not] really relevant". And where they do matter to multi-threading (the shared memory part), Rust does help with correctness.


Eh, modern OS-es indeed have loads of problems still, of which non-transactional access to the filesystem is in my top three, but to put those problems on Rust is a bit uncharitable. It's not Rust's fault that zero kernel devs have the courage to finally start enforcing patterns that have proven themselves useful and safe for decades, in other areas outside of IT as well (i.e. in financial accounting).

Rust plucks the fruit it can reach and it mostly stays in its lane and it's trying to expand it here and there (like Rust in Linux and embedded). I too want one ultimate language and one ultimate kernel but I don't think you and I will live to see it. Maybe our grandchildren will not as well.


It's great that they finally target all three mayor platforms! Let's see how developers using Windows treat them. I used to be a Neovim purist, spending days on my config and I have barely touched it since I moved to Zed. It's so much nicer to use then VScode (and it's forks) because it's so snappy. I hope they ship leap.nvim (https://github.com/ggandor/leap.nvim) support soon, then I am completely happy!


It's great that they finally target all three mayor platforms! Let's see how developers using Windows treat them.

I used to be a Neovim purist, spending days on my config and I have barely touched it since I moved to Zed. It's so much nicer to use then VScode (and it's forks) because it's so snappy.

I hope they ship leap.nvim (https://github.com/ggandor/leap.nvim) support soon, then I am completely happy!


Very cool! Since it’s possible to train foundation model adapters, is a library for user fine tunes possible?


Not yet, but can be supported in the future


As pointed out in other places as well a better comparison will be the upcoming Pro & Max variants. Also, as far as I know, Strix Halo mainly uses the GPU for inference not the little AI accelerator AMD has put on there. That one is just to limited.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: