Rust API Guidelines Checklist
rust-lang.github.io
rust-lang.github.io
By no means should anyone be intimidated by this. This list is, well, something like a code review guide similar to what you'd find to make changes to Postgres or Python. New APIs that are part of the standard library need to be be consistent, performant, debuggable, documented, and so on.
Following this list for a hobby, side project, or for the 0.1.0 release of a new library is entirely unnecessary.
This may be a hot take, but I'll go and take my chances.
Following this list for a hobby or side project or even an initial release of a library is a very good idea. It's hard to tell what kinds of libraries will or won't catch on. As soon as you have downstream users, they will get annoyed by churn. If given a checklist, it seems reasonable to me to expect people to actually follow it out of obligation to your future downstream consumers of the library.
Not only that, but I believe that most of the things on that list boils down to good engineering. Following good practice early on even just in a hobby/side project will be rewarded as the project grows.
By releasing a library (even as a 0.1.0), you imply that you expect it to be at least usable for some kind of usage. Releasing known-bad code is something nobody would do, especially since every major Git repostory hoster lets you have private repositories.
Mmm. I guess it depends how mischievous people are.
Is https://crates.io/crates/misfortunate known-bad code? Take misfortunate::Comte which claims to be an ExactSizeIterator but lies and with a simple "tap" from your wand produces an infinite number of cloned Rabbits ?
OK, how about Mara's https://crates.io/crates/whichever-compiles or https://crates.io/crates/nightly-crimes ?
I mean, maybe I'm a bad person for writing misfortunate, but is Mara, Rust's library team lead, a bad person?
Fortunately, these people are very clever, very good Rust developers and they are not maliciously dropping nightly crimes into widely used crates :)
> This is a set of recommendations on how to design and present APIs for the Rust programming language. They are authored largely by the Rust library team, based on experiences building the Rust standard library and other crates in the Rust ecosystem.
GitHub repo for the guidelines:
https://github.com/rust-lang/api-guidelines
I am submitting the OP link to HN because I believe that these guidelines are useful to many people that have, or wish to, publish Rust crates that other people will then use.
Following these guidelines will make the crates we make feel "native to Rust" for other people that want to make use of our crates.
I found these guidelines just a couple of days ago for the first time, in spite of having written Rust for several years now. And I suspect that many others may not have read these guidelines and that others will benefit from reading them too.
document.querySelectorAll('input:disabled').forEach((el) => el.disabled = false)If you're really impatient you can implement the trait yourself (with some hacking involved): wrap the type in a new struct and implement the trait there.
Why hacking around like that? Rust requires at least one of: the type, or the trait; to be originated in your crate.
So you live with it. If you draw a comparison to C++, almost none of these things are implemented for dependencies and there's no easy helper to add it.
API names and such are of course breaking changes, but unless you're authoring Tokio or Hyper or another huge, important crate in the ecosystem, it's really not worth it to do everything on this list.
> Types eagerly implement common traits
This is particularly concerning to me for multiple reasons. If my 4K structure can be copied, should it derive `Copy`? This leads to users implicitly copying it around instead of using references more aggressively.
If all my types implement `PartialEq`, `Debug`, and other stuff, that means a lot of code generation at compile time, which gets hopefully eliminated by LLVM passes. And then we are wondering why Rust compilation/linking is so slow :/
Rust eliminates unnecessary memcpys, but this is a bit up to you. `Copy` as a synonym of "cheap to copy" is used by some crates, although this is not official AFAIK.
> If all my types implement `PartialEq`, `Debug`, and other stuff, that means a lot of code generation at compile time,
If you don't use these, no LLVM-IR is even generated for these. Rust compiles code "on demand".
Once Copy/Debug/PartialEq are derived, it will be tempting to use them, so the compile time cost will apply.
If you don't want to use a standard library that follows these, just fork it and change it. Rust makes this trivial, and projects that must do this go and just do it.
I really don't know what point you are trying to make. Implementing Copy for all types that are cheap to copy makes sense for most Rust programmers.
That does not mean that it makes sense for _you_, but if you disagree about this not making sense for most, then Rust is probably the wrong language for you, and you should consider using something else.
If you're exaggerating and the object is really 64 bytes, just suck it up and derive Copy, your estimate of how "expensive" it is may well be so wrong that you're defeating your own objectives.
I've never seen any indication that unneeded PartialEq or Debug for example aren't elided by the compiler. In contrast if I need Debug it sure is a pain in the backside to implement it manually in a wrapper type because the owner of the type decided unilaterally that nobody would need that.
https://rust-lang.github.io/rust-clippy/master/#large_types_...
The default threshold is 256 bytes: https://github.com/rust-lang/rust-clippy/blob/1fc1aee7be6e7e...
So you might use that as a rule of thumb. But officially, "Generally speaking, if your type can implement Copy, it should." https://doc.rust-lang.org/std/marker/trait.Copy.html#when-sh...
On projects I work on, I include clippy as part of the CI process to check these types of things.