This is one of the biggest advantages of the newer wave of more expressively typed languages like Rust and Swift.<p>They remove a lot of ambiguity in how something should be held.<p>Is this data type or method thread safe? Well I don’t need to go look up the docs only to find it’s not mentioned anywhere but in some community discussion. The compiler tells me.<p>Reviewing code? I don’t need to verify every use of a pointer is safe because the code tells me itself at that exact local point.<p>This isn’t unique to the Linux kernel. This is every codebase that doesn’t use a memory safe language.<p>With memory safe languages you can focus so much more on the implementation of your business logic than making sure all your codebases invariants are in your head at a given time.
In the beginning, I was trying to use Rust like C (which I think lot of people do) and was struggling with the borrow checker. I had a light bulb in my head one day to read the function signature and see if its '&self' or '&mut self'.<p>If any one API of a struct/enum has '&mut self' then its instance cannot be shared across threads without using a mutex (which brings its own friend along i.e Arc). This led me to structure the code in my mind much in advance to prevent borrow checker issues.<p>Another use of this is while embedding an object in a struct. When I realized that '&mut self' infects everything up the call chain it was a big learning moment. That is the embedding struct also needs a mutable borrow as well.
There are tons of underdocumented Rust libraries, where I've had to pore over it for very long periods of time because the author probably thought the code would speak for itself and not bother writing any documentation strings on any of the functions.<p>No, Rust doesn't solve the problem of incomplete API docs. Developers being diligent enough to document the APIs solves the problems, and that solution is entirely language-independent.
>But the end result of all this is that you CAN, in fact, just look a the Rust API and know how to use it correctly for the most part.<p>For this I have to bring up that there are indeed rust API's that I have to Google around a bit because I have no way of knowing just by looking at the function signature how to create the type that it expects. Because some types you can't just make from scratch and have to use a combination of other functions to create.
IDK if this is bad practice but I've rolled up the messages if you wanna read this in one view:<p><a href="https://gist.github.com/shmup/d6290988c876c303663d56563bc5705d" rel="nofollow">https://gist.github.com/shmup/d6290988c876c303663d56563bc570...</a>
You can also state this without the Rust involvement: adding a duplicate of the APIs in any other dialect, going through that exercise pushes implementors to reach clarity and understanding that is more detailed and complete than any incremental code review, and you can benefit greatly if you utilize that feedback in a timely fashion to improve the code and/or docs. There's an interesting parallel here to one of the common rust feedback tropes: until rust has two implementations and a specification it's not ready; this is interesting to reflect on in context.<p>This also came up in the video referenced in the step-down announcement, specifically just before Ted jumped in all hot, they were in the middle of about to propose to take some of what had been learned and perhaps rename or even document the C side once it was understood. Amusingly/disappointingly that suggestion which was coming was also counter to what Ted assumed they were saying.<p>A recent personal experience example down this same path happened in the GSO paths in the network stack, where a well intentioned incremental linux change made its way through review, landed not only in head but also into stable and LTS before anyone noticed that it was broken. It had actually broken kselftests (noted by a maintainer after the report it was broken), but kselftests is quite a mess to use on any given day, so it's hard to "spot" regressions and demonstrably isn't used as a tool to guard against regressions consistently. Reviewers missed the semantics, and i wouldn't blame them because it turns out the semantics in question aren't explicitly or clearly written down anywhere. Last year we wrote against this interface at work, and gained substantial performance improvements, but to do so we had to read the docs, read the source, read the review threads, make assumptions, try stuff, and ultimately settle on the observed semantics more than anything else. This is a userspace interface, so it should be well defined and stable following the mantra, and it's mostly ossified now due to having real users, but it's not well documented or well understood. We follow along some of our fellow offload implementors and have seen a number struggle trying to work solely off of the docs and looking at our implementation, as they miss minor semantics - you can only get those by reading the source and patches very closely. The point of this story is that these problems of understandability cause regressions inside the kernel too, all the time. Reaching for tools to avoid this is a good idea.
> Does a ref counted arg transfer the ref or does it take its own ref?<p>This sort of thing also comes up a lot when you write Python extensions in C. You have to know the "calling convention" when you pass object refs in and out of functions. This entire category of problems goes away when you write extensions in Rust with PyO3, and the barrier to entry for new folks is much lower. C++ can do similar things (std::shared_ptr), but it tends to introduce new footguns in a way that Rust really doesn't.
Concrete example for those not familiar with Rust:<p>In most languages, you have a lock on the side that you need to remember to take to protect some data. In Rust, the lock wraps the guarded data, you can't access the data without holding the lock, you can't forget to unlock, and you can't keep a reference alive while releasing the lock.<p><a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html" rel="nofollow">https://doc.rust-lang.org/std/sync/struct.Mutex.html</a><p><a href="https://doc.rust-lang.org/std/sync/struct.MutexGuard.html" rel="nofollow">https://doc.rust-lang.org/std/sync/struct.MutexGuard.html</a>
Another perspective which makes it clear this is The Way: it brings the promise of fully self-documenting code much closer to fruition, if not all the way!