6 ms·
> Rust is a systems programming language. It offers precise control over data layout and runtime behavior of the code... It really doesn't. It doesn't even hav
by ajxs 5y ago
> Rust is a systems programming language. It offers precise control over data layout and runtime behavior of the code...
It really doesn't. It doesn't even have native support for bitfields. When I tried doing low-level programming in Rust, this immediately struck me. Rust's semantics don't really offer much of an improvement over what already existed in this area. In addition to presenting all kinds of new, frustrating challenges. I've used Ada extensively in this area, and I just don't see what Rust has to offer that Ada didn't already address.
I'm all too aware that string operations in low-level programming languages are always going to be prickly. Ada's standard library, even in its 80s incarnations, is light-years ahead of Rust in this area. Interoperability with other languages is another area where Ada beats Rust hands-down. The first thing I tried to do was integrate C and Rust, and realised immediately that it was a nightmare. In Ada, it really couldn't be simpler.
- zozbot234 5y ago> It really doesn't. It doesn't even have native support for bitfields. Many people would consider C bitfields half-baked in the first place, given that the feature is well-known to be underspecified in a way that leads to compatibility/portability concerns. Is this really the kind of stuff that Rust should concern itself with?
- pitaj 5y agoYeah I agree with rust's decision to not go there yet. They're only really used often in very low-level niches like mmio registers, where autogenerating handlers with svd2rust works great and provides a little bit of safety along with it. This is coming from someone who uses C bitfields every day on an embedded MCU.
- ajxs 5y ago> They're only really used often in very low-level niches like mmio registers ... which are actually an incredibly common, totally everyday problem encountered by tens of thousands of developers everyday? > autogenerating handlers with svd2rust works great and provides a little bit of safety along with it. I don't think that requiring third-party tooling to implement something so basic is a suitable solution to this problem. What if the manufacturer of the device I'm working with hasn't released an SVD file? What if I'm not actually working on an MCU at all, but a peripheral driver?
- pitaj 5y ago> actually an incredibly common, totally everyday problem encountered by tens of thousands of developers everyday I never said they're umcommon. As I said, I user them all the time. They're incredibly common in specific fields. There are many systems programmers who barely ever use them. There are a lot of footguns with bitfields in C. (1) they know nothing about defaults, (2) they have no way of restricting values beyond bitwidth, (3) they are often inefficient, producing multiple load-modify-stores for what is really a single operation, (4) they are not endian portable. svd2rust addresses all of those: (1) it knows what the defaults are and you can tell it to load them for you, (2) it will restrict the values for each field to only those that are valid (you can use unsafe to bypass the check), (3) it produces a single load-modify-store (or less) for any given operation, (4) it produces shifts and masks internally so doesn't depend on the compiler to behave as expected. Of course, C bitfields don't require tooling, and I'd say they're a little easier to use. It's a trade-off, and I personally prefer the rust side. > I don't think that requiring third-party tooling to implement something so basic is a suitable solution to this problem. Don't most people auto-generate bitfields, too? Like sure, writing a couple by hand is fine, but I didn't think that's typical. > What if the manufacturer of the device I'm working with hasn't released an SVD file? What if I'm not actually working on an MCU at all, but a peripheral driver? You can write your own SVD, or write yaml and convert that to SVD. I think that would probably work for a peripheral driver, too.
- jandrewrogers 5y agoBitfield equivalent constructs are used more ubiquitously than just embedded. For example, in database engines the size of internal types are often defined in bits that aren't multiples of bytes, and they are packed and composed accordingly. Good implementations use a bit of meta-programming magic to make them seem more natural but they aren't something C++ was really designed to support. I think there is an opportunity for a systems language to do bitfield types right, which means not copying C.
- pitaj 5y agoI agree that there's certainly usefulness for bitfields in the industry, but I haven't seen a good proposal that addresses the main issues that C bitfields have. And in rust, any given proposal wouldn't be super useful if it always required unsafe.
- zozbot234 5y agoThe Rust standard library should concern itself with very general patterns that could feasibly enable interoperability across crates. I'd rather see a generalized facility for working seamlessly with composable 'optics' on Rust structs/objects (similar to the existing support for Iterators) than something strictly focused on the bitfield case.
- ajxs 5y agoBitfields are a construct that I use all the time in my work. If Rust chooses not to implement semantics for defining bit-level fields, then it's just harder for me to accomplish what I need to using Rust. Again, bitfields are something that Ada makes simple, and easy. Granted, I think Ada's syntax for this could be improved. I don't see the relevance in pointing out that the C standard has problems related to bitfields. Rust is supposed to be an improvement upon C.
- zozbot234 5y ago> If Rust chooses not to implement semantics for defining bit-level fields Look, it's not that hard. Just write getters and setters for the underlying structs, and you'll pretty much reach parity with what C gives you (but in a well-specified way). There are crates that will make this easier.
- tempodox 5y ago“Language X has implemented this badly, why should language Y bother with it” isn't really a convincing argument.
- msbarnett 5y ago> I've used Ada extensively in this area, and I just don't see what Rust has to offer that Ada didn't already address. Memory safety guarantees that don't go out the window if you ever need to free a dynamic allocation, for starters. Bitfields are an underspecified minefield in C, I don't think it's as clear of a loss as you're making it sound.
- ajxs 5y agoLike I said above, I don't see the relevance in pointing out that the C standard has problems related to bitfields. Rust is supposed to be an improvement upon C. Ada managed to implement a standard for defining structures at the bit level in a portable way back in the 80s. Saying that Rust can't do it now because the C standard doesn't sufficiently specify bitfield semantics isn't a good answer.
- msbarnett 5y ago> Saying that Rust can't do it now because the C standard doesn't sufficiently specify bitfield semantics isn't a good answer. I don't think anybody is saying that? Particularly given that Rust is working on precisely that. The argument is merely that not currently having a good bitfield solution is hardly a showstopper for systems development, given that C is already far more popular in that area than Ada despite its deeply deficient version of bitfields which leads to them being banned in a great many codebases.
- pyjarrett 5y ago> Memory safety guarantees that don't go out the window if you ever need to free a dynamic allocation, for starters. Lots of people like to repeat this without understanding all of the other controls that Ada has for access types (pointers). Ada access types (like pointers) are typed so you could make multiple equivalents of `Foo` that can't be mixed and matched. e.g. one version of `Foo` might be for one subsystem and another version of `Foo* for a different subsystem, which would prevent you from giving an allocated object from one system to another. You also can't point an access to any arbitrary location without it being specifically marked with `all`, and there's limitations to how you can use an access that gets passed as a parameter. Due to these factors, how allocations can be used gets constrained and with Ada's support for RAII ("controlled types"), these details usually get hidden internally within types. It's not a specific block section like `unsafe`, but your unsafe memory usage is helped by the type system.
- jandrewrogers 5y agoTo be fair, the problem with C bitfields that causes them to be forbidden in many coding standards is that don't offer "precise control over data layout". They are underspecified, so a lot of C/C++ code bases construct bitfields explicitly and manually (and these have other advantages anyway). And of course you can do the same in Rust. Rust has limitations as a systems language but this isn't one of them.
- ajxs 5y agoWhat do you mean this isn't one of Rust's limitations? It's a common, well-understood feature of systems languages, which Rust doesn't have. Look for yourself on Rosetta Code[0]. There are many languages that feature a way to define a structure with individual bit fields: Basic, Fortran, Ada, etc. [0]https://rosettacode.org/wiki/Memory_layout_of_a_data_structure https://rosettacode.org/wiki/Memory_layout_of_a_data_structu...
- nextaccountic 5y agoBitfields are hard! They are potentially unaligned, thus interact poorly with some language features, like pointers and references. And their size isn't a multiple of bytes, unlike any other value, which causes problems as well. They interact poorly with padding and the general idea of Rust ABIs that enables optimizations like reordering fields and using "niches" (invalid values) to find a more compact layout for structs and enums. I agree Rust should eventually have some native support for bitfields, but only if it's a high quality spec that addresses the outstanding concerns - Rust should specifically avoid the C mess, which isn't usable for most projects. But this doesn't mean bitfields can't be done in Rust; it's just not in the stdlib (yet). See this post[0] which contains a survey of various libraries (and their respective limitations), and this slightly older article [1]. Those articles somehow missed the modular-bitfield crate [2], which is perhaps the nicest to use, and is what I would recommend you. If you don't care about the specifics you can get any crate discussed in the above articles and use them. About interoperability with C (and C++), I really like bindgen, cbindgen and cxx. The bindgen book [3] is straighforward. This section of cxx documentation [4] also describes the tradeoffs between the different FFI approaches. I don't know Ada though, so I must ask: what does Ada do? About this, > I just don't see what Rust has to offer that Ada didn't already address. Off the top of my head, the crates ecosystem, the borrow checker, sum types with pattern matching [5], a stellar story for error handling (beats any language I know hands down - that is, if you use crates like thiserror and anyhow). [0] https://immunant.com/blog/2020/01/bitfields/ https://immunant.com/blog/2020/01/bitfields/ [1] https://myrrlyn.net/blog/misc/bitfields-in-rust https://myrrlyn.net/blog/misc/bitfields-in-rust [2] https://crates.io/crates/modular-bitfield https://crates.io/crates/modular-bitfield [3] https://rust-lang.github.io/rust-bindgen/ https://rust-lang.github.io/rust-bindgen/ [4] https://cxx.rs/context.html https://cxx.rs/context.html [5] https://chadaustin.me/2015/07/sum-types/ https://chadaustin.me/2015/07/sum-types/
- ajxs 5y ago> Bitfields are hard! They are... Again, like so many others in this thread, you're talking about C's problems. C is not the only language to implement this feature. I keep bringing up Ada because it's a language that features the ability to define structures at the bit level in its core language semantics. It manages to do this in a portable way, with a much more sophisticated, not to mention sound type system. > But this doesn't mean bitfields can't be done in Rust... Why should users need to rely on installing third-party additions in order to do something so basic like this? With the addition of third-party frameworks, and tooling you can make C as safe as Rust too, so I don't think the argument that third-party dependencies can solve this problem are relevant. I'm judging these languages simply on how well they allow me to express the semantics required for low-level programming. > About interoperability with C (and C++), I really like bindgen, cbindgen and cxx. The bindgen book [3] is straighforward... Ada comes out of the box with this functionality. It doesn't require reading a 'book' to understand it either, it's very straightforward. > beats any language I know hands down - that is, if you use crates like thiserror and anyhow... Again, why should someone need to install third-party tooling and dependencies for such basic features? The fact that so many responses list a litany of external dependencies to address Rust's shortcomings does not lend much credibility to Rust's design.