2019년 1월 10일 목요일

Proposed Rust community norm for unsafe code

Recently cessen asked people to write their thoughts on Rust community norm for unsafe code. So here it is.

I recommend reading the whole article, even if it is somewhat long. I will quote what I consider to be its essential point, but my quote will necessarily lose nuances.
Rust community's attitude towards unsafe code is something along the lines of, "Don't ever use it unless you're a wizard... and you're not a wizard."
I strongly reject this attitude. I believe this does not match Rust's design intent.
Different software has different needs, and I don't think a one-size-fits-all attitude towards unsafe code makes sense.
I also strongly reject this proposal. Shared community norm is valuable. I fear difference here can result in ecosystem split. Due to network effect, one-size-fits-all can make sense even if one size does not fit all, if suboptimality is compensated by community size.

Examples of shared community norm I noticed include expectation of portability in C, expectation of freeing memory in C, expectation of referential transparency in Haskell, expectation of non-blocking in Node.js, etc. For some software, it is entirely reasonable not to free memory in C (your program always allocates less than 1 GB), write side-effecting pure function in Haskell (for debug logging), block in your Node.js library for computation (you should wrap it in thread if you need it in non-blocking context), etc. but it is understood that this is just not done, for code intended to be shared and reused by others, because it breaks expectation and is egregious violation of principle of least surprise.

One important question is what this norm should be. I propose "Rust library should strive to have correct safety declaration in the interface". Let me explain word by word.

"Rust library". I think it is okay to hold applications, aka code not intended to be reused, to less standard.

"should strive". Making mistakes is okay and does not count against you, that is, not more than any other bugs. On the other hand, community norm is that these are bugs, and are expected to be fixed. Note that IT CAN ALWAYS BE FIXED, even if actually doing so is a bad idea because it is API breakage: you can change any such "fn" to "unsafe fn".

"to have correct safety declaration". This is to be fixed in stone by unsafe code guideline, but general outline, I think, is easy. Using your code, safe code should not be able to perform use-after-free, to produce aliased &mut, etc etc.

"in the interface". As long as the interface is safe, any use of unsafe in the implementation is fair game and does not count against you and lots and lots of uses of unsafe is not a reason to avoid the library. I mean, "std" is full of them. Go look at it.

Thanks for reading. Please comment on /r/rust subreddit.