I wish that there was a useful “freeze” intrinsic exposed, even if only for primitive types and not for generic user types, where the values of the frozen region become unspecified instead of undefined. I believe llvm has one now?
Iirc the work on safe transmute also involves a sort of “any bit pattern” trait?
I’ve also dealt with pain implementing similar interfaces in Rust, and it really feels like you end up jumping through a ton of hoops (and in some of my cases, hurting performance) all to satisfy the abstract machine, at no benefit to programmer or application. It’s really a case where the abstract machine cart is leading the horse
Write into uninit'd buffers was one of the pain points of Rust for the creator of the new open source "edit" program for Windows[1]. I wonder what he thinks of this article.
> Another thing is the difficulty of using uninitialized data in Rust. I do understand that this involves an attribute in clang which can then perform quite drastic optimizations based on it, but this makes my life as a programmer kind of difficult at times. When it comes to `MaybeUninit`, or the previous `mem::uninit()`, I feel like the complexity of compiler engineering is leaking into the programming language itself and I'd like to be shielded from that if possible. At the end of the day, what I'd love to do is declare an array in Rust, assign it no value, `read()` into it, and magically reading from said array is safe. That's roughly how it works in C, and I know that it's also UB there if you do it wrong, but one thing is different: It doesn't really ever occupy my mind as a problem. In Rust it does. [https://news.ycombinator.com/item?id=44036021]
> without doing anything hugely inefficient, such as initializing the full buffer
Is this so inefficient? If your code is very sensitive to IO throughput, then it seems preferable to re-use buffers and pay the initialization once at startup.
Some years ago, I needed a buffer like this and one didn't exist, so I wrote one: https://crates.io/crates/fixed-buffer . I like that it's a plain struct with no type parameters.
Just dropping to C for a smallish segment of a rust program kind of makes sense if you want to eke out performance here, no?
With so much unsafe, it makes me think of that fun experimental usage of rust : https://github.com/tsoding/Crust
Related to unspecified vs undefined. I recall some C code was trying to be tricky and read from just allocated memory. Something like:
int* ptr = malloc(size); if(ptr[offset] == 0) { }
The code was assuming that the value in an allocated buffer did not change.
However, it was pointed out in review that it could change with these steps:
1) The malloc allocates from a new memory page. This page is often not mapped to a physical page until written to.
2) The reads just return the default (often 0 value) as the page is not mapped.
3) Another allocation is made that is written to the same page. This maps the page to physical memory which then changes the value of the original allocation.
Pardon my ignorance, but I thought the whole point of Rust was to be a 'safe' modern alternative to C, so all new buffers would be zero'd at a neglible-these-days cost. Why is rust half-assing this?
Couple of things that are commonly misunderstood/unappreciated about this:
• Uninitialized bytes are not just some garbage random values, they're a safety risk. Heartbleed merely exposed unitialized buffers. Uninit buffers can contain secrets, keys, and pointers that help defeat ASLR and other mitigations. As usual, Rust sets the bar higher than "just be careful not to have this bug", and therefore the safe Rust subset requires making uninit impossible to read.
• Rust-the-language can already use uninitialized buffers efficiently. The main issue here is that the Rust standard library doesn't have APIs for I/O using custom uninitialized buffers (only for the built-in Vec, in a limited way). These are just musings how to design APIs for custom buffers to make them the most useful, ergonomic, and interoperable. It's a debate, because it could be done in several ways, with or without additions to the language.