My chosen learning project in Rust was to write a simple IRC server. As a service daemon with no real-time requirements written around a state machine of the kind I can code practically in my sleep, I thought this would make a good warmup for NTP.

I wrote the following summary four days into the attempt…​

In practice, I found Rust painful to the point of near unusability. The learning curve was far worse than I expected; it took me those four days of struggling with inadequate documentation to write 67 lines of wrapper code for the server.

Even things that should be dirt-simple in Rust, like string concatenation, are unreasonably difficult. The language demands a huge amount of fussy, obscure ritual before you can get anything done.

The contrast with Go is extreme. By four days in of exploring Go I had mastered most of the language, had a working program and tests, and was adding features to taste.

Then I found out that a feature absolutely critical for writing network servers is plain missing from Rust. Contemplate this bug report: Is there some API like "select/poll/epoll_wait"? and get a load of this answer:

We do not currently have an epoll/select abstraction. The current answer is "spawn a task per socket".

Upon further investigation I found that there are no proposals to actually fix this problem in the core language. The comments acknowledge that there are a welter of half-solutions in third-party crates but describe no consensus about which to adopt.

After publishing a version of this critique on my personal blog I learned a good deal more from various thoughtful members of the Rust community (as well as attracting a lot of flamage from some less thoughtful members).

At the present time, the following problems - acknowledged by those more thoughtful Rustaceans - make Rust unsuitable as an implementation language for NTP:

The language is not yet mature enough to present a core API that can be expected to be stable over 10-year timescales.

As a special case of the previous point, primitives required for NTP such as select/epoll are not yet a stable part of the language. While implementations exist in the crate system, there is not yet any guarantee that any of the alternatives will be maintained over 10-year timescales.

The language documentation describes the Rust compiler well, but fails to bridge the explanatory gap to parts of the crate system vitally needed to use the language as a production tool.

More generally, a lot of crucial information about the language in practice is not yet documented at all; you have to be part of the swarm around the development group and follow their communications channels to learn it.

These problems seem to reflect a social/philosophical confusion in the Rust community about whether and when they will "bless" crates, designating them as part of a core API with stability guarantees. Rust has a Conway’s Law problem: the decentralized structure of the crate system tends to discourage making this kind of commitment at all.

Go has a not entirely dissimilar package system, but the Go designers made an early choices to define a set of core modules much more extensive than Rust’s - one which does include, in particular, all the primitives required to implement network service daemons.

Additionally, the core Rust language has a serious learning-curve problem that present documentation and tutorials don’t address effectively enough. Relatedly, the friction cost of important features like the borrow checker is pretty high. This would translate into continuing barriers to entry for NTP developers.