← Back to context

Comment by weinzierl

18 hours ago

I'd curious about the banned Rust features. Surely, Rust has at lot fewer foot guns, but it isn't that there aren't any.

Rust has been better than C++ about marking where there's a foot gun and where practical just nerfing it. core::mem::uninitialized() is an example. In 2016 if you'd said "Initializing my Doodad is too expensive, what do I do?" you might be pointed at the (unsafe) core::mem::uninitialized() which "initializes" any variable, such as your Doodad but er, doesn't actually initialize it.

But that's a foot gun, there are niche cases where this crazy stunt actually is correct (ZSTs are one), but in general the compiler was in effect licensed to cause absolute mayhem because this isn't a Doodad at all, which isn't what you wanted. So, they did three things:

1. Made a new type wrapper for this purpose, MaybeUninit<Doodad> might not be a Doodad yet, so we can initialize it later and until then the compiler won't set everything on fire but it's the same shape as the Doodad.

2. Marked core::mem::uninitialized deprecated. If you use it now the compiler warns you that you shouldn't do that.

3. De-fanged it by, despite its name, scrawling the bit pattern 0x01 over all the memory. The compiler can see this has some particular value and for common types it's even valid, a bool will be true, a NonZeroU32 will be 1, and so on. This is slow and probably not what you intended, but we did warn you that it was a bad idea to call this function still so...

Heard of `#![forbid(unsafe_code)]` ?

  • It's that effectively enforcement of features that are banned?

    • Rust's compiler has six what it calls "lint levels" two of which can't be overridden by compiler flags, these handle all of its diagnostics and are also commonly used by linters like clippy.

      Allow and Expect are levels where it's OK that a diagnostic happened, but with Expect if the diagnostic expected was not found then we get another diagnostic telling us that our expectation wasn't fulfilled.

      Warn and Force-Warn are levels where we get a warning but compilation results in an executable anyway. Force-warn is a level where you can't tell the compiler not to emit this warning.

      Deny and Forbid are levels where the diagnostic is reported and compilation fails, so we do not get an executable. Forbid, like Force-warn cannot be overriden with compiler flags.