Const Generics in Rust
nora.codes
nora.codes
I recently had to use "FixedBitSet" in Rust. This is simply a set of N bits. It's the clean way in Rust to do bit-banging. Unfortunately, the underlying implementation is a dynamically allocated Vec. So, when you do bitset.set(4,true), far more code is generated than just one OR instruction.
So, it's not quite here yet.
How many?
Because looking at ARM and C with an unpacked bitfield structure, you’ll have 3 or 4 easily. A load, some shift, or, store. Anytime I see a bitfield in C I assume 4 instructions. So is this close?
https://godbolt.org/z/7Tbzhx5Kc
Rust is a very nice language, but I feel they forgot to copy some useful features from other languages.
Right now in the Const Generics MVP you can only use integer types. So you can write a generic argument with an u32 N in it, or a char C (a Unicode scalar, so basically a "character" in Unicode) or something like that. There are a bunch of practical uses for this, but obviously there's no reason in principle it must be so limited.
In C++ there's always a temptation to just rip the knob off, sure it might be a terrible idea to make a new type generic over the 32-bit floating point numbers, but that's your problem as the developer right? Just don't do that if you're uncomfortable cleaning up the mess. Rust does not like to provide so many foot guns.
So the last time I looked the proposal was that user-defined types could be eligible for const generic treatment if they derive Eq.
At the first glance that sounds correct, if the type is Eq then it can make sense to be generic over it since apparently we can tell when A = B and thus whether Foo<A> is actually the same as Foo<B> or different.
But then an extra thought brings you up cold. I can claim my type is Eq with one line if it's PartialEq. And I can claim my types are PartialEq just by providing a bogus eq() function that always says false. So isn't this a useless requirement?
And then you study the language more carefully. They're going to require that you get Eq by deriving it. Anybody can implement PartialEq as I described above, but that's not derived. To get a derived PartialEq (and thus Eq) the derive macro has to allow that, and that's only going to work for the kind of composite types a non-crazy person would use for const generics.
Your trivial enumerated type with a list of fifteen types of chocolate bar can easily derive Eq if you want to write const generics so that somebody can make a variable of type AdventCalendar<Chocolate::Mars> in this future Rust version, but my custom type that contains two pointers to C Strings can't successfully derive Eq and so isn't eligible to try to be used for const generics even if it really genuinely implements Eq.
[0]: https://en.cppreference.com/w/cpp/language/template_paramete...
Admittedly it can be nice not to be at the mercy of the optimizer. And getting compiler errors instead of runtime panics is a really great benefit. But I've just become slightly wary of big performance claims these days. Perhaps I'm just getting too cynical.
I imagine this basically gives you that. But do other languages do this? I’m guessing maybe functional programming languages?
It’s something I actually miss in modern mainstream languages. But as it’s something few copied and few lament, we can extrapolate that I’m a minority :)
C99 has something similar but different in that integer fields in a struct can have a bit width specifier. This is is primarily used for bit fields in protocol frames and things, and conventional wisdom is that compilers generate poor code for them even today, and doing your own bit masks instead is still popular.
What happened instead was standardized hardware. The 60 bit CPUs, the 48 bit CPUs, the 36 bit CPUs, the 24 bit CPUs, the 18 bit CPUs, and the 12 bit CPUs all died off. With everybody using powers of 2 of bytes, range calculation became less important for portability.
WUFFS is in a related place to something like Coq. The idea in WUFFS is, if I write my decoder for the FOO image format in WUFFS, no matter how lazy and incompetent I am, your image displaying program can confidently use my FOO decoder, and if I did a bad enough job it might be slow or produce the wrong picture but it can't crash or run a SSH server or delete the password database or whatever.
C has been a headache in many ways, but one thing I've noticed is that there are many examples of very, very long-lived C projects, and not very many examples of very, very long-lived projects in most other languages (IBM, obviously, will disagree here, and COBOL). Some of that is related to C being a good fit for generating economic value at the beginning of the era that would now qualify as very long lived (20+ years, 30+ years), I'm sure, but it is interesting to consider that parts of some languages will not age well.
Of course there are, because that's the 'native' language for all Unix' and Unix-lookalikes and Windows because of the Kernels in C. So, for any OS relevant for 'real' computers of the last 30 years. Had the Lisp-Machines won the battle, nobody would talk about C any more (or just to scare children like with COBOL). And don't forget about Fortran, there is some _really_ ancient Fortran code in use at the same places that still use their COBOL.
No, they shouldn't. Would really prevent many subtle bugs if the default integers of every language would be arbitrary precision ints.
Things quickly get interesting interoperating with other languages eg via json.
struct MyIndex<const MIN: usize, const MAX: usize> {
index: usize, MIN/MAX??
}
That would get rid of lots of runtime bound checks.https://play.rust-lang.org/?version=nightly&mode=debug&editi...
Edit: I'm honestly surprised at how usable this is already in the current state of nightly:
https://play.rust-lang.org/?version=nightly&mode=debug&editi...