There are plenty of language ecosystems where there's no particular expectations up front about whether or when a library will do IO. Consider any library that introduces some sort of config file or registry keys, or an OS where a function that was once purely in-process is extracted to a sandboxed extra process.
> There are plenty of language ecosystems where there's no particular expectations up front about whether or when a library will do IO.
There are languages that don't enforce the expectation on a type level, but that doesn't mean that people don't have expectations.
> Consider any library that introduces some sort of config file or registry keys
Yeah, please don't do this behind my back. Load during init, and ask for permission first (by making me call something like Config::load() if I want to respect it).
> or an OS where a function that was once purely in-process is extracted to a sandboxed extra process.
Slightly more reasonable, but this still introduces a lot of considerations that the application developer needs to be aware of (how should the library find its helper binary? what if the sandboxing mechanism fails or isn't available?).
For the sandbox example I was thinking of desktop operating systems where things like file IO can become brokered without apps being aware of it. So the API doesn't change, but the implementation introduces IPC where previously there wasn't any. In practice it works fine.