> Then why do functions with sync syscalls (ie file, timers or mutex ops) not expose the same contractual differences? They’re just regular functions in most languages including Rust.
Because the kernel doesn't expose that contract, so they don't have that behaviour.
> The only difference is whether the runtime sits in the kernel or in user space.
In other words, what contracts you have control over and are allowed to provide.
> My take has been for years that this is throwing complexity over the fence and shaming users for not getting it.
I'm sure how we got here would seem baffling if you're going to just ignore the history of the C10K problem that led us to this point.
You can of course paper over any platform-specific quirks and provide a uniform interface if you like, at the cost of some runtime overhead, but eliminating as much of this kind of implicit runtime overhead as possible seems like one of Rust's goals. Other languages, like Go, have a different set of goals and so can provide that uniform interface.
It's probably also possible to have some of that uniform interface via a crate, if some were so inclined, but that doesn't mean it should be in the core which has a broader goal.