It has been pointed out that Effects keep coming up because my description may lead people in that direction. What I’m actually talking about is more like module-scoped capabilities. It’s perhaps best described in sequence.
Imagine you’ve got some Rust code in which you cannot import any libraries at all and cannot use unsafe. With such code, as long as Rust itself is not broken, you cannot do anything but compute (and allocate supporting memory). There’s no file access, network access or system access of any kind. But there’s also no vector classes, no mathematical operations beyond the basic operators, and a number of other missing features.
There is a subset of the standard library that provides vector classes, mathematical operations and other things. These provisions still don’t allow file, network and runtime-bypass abilities and so are safe for anyone to use, even if some users are malicious.
Then there are parts of the standard library (and
unsafe) that do provide malicious or exploited actors with a lot, like the aforementioned abilities to access files, access the network and bypass runtime safety.
If you could specify that some library only had access to the safe subset that could work in isolation from an OS, and whatever additional libraries you whitelist, then you would know it could not either drain your bitcoin wallets or accidentally allow others to do so.
Note that allowing access to some library that can access files (like a timezone library accessing the tzinfo file or a logging library outputting to a known location) is fine. As long as Rust’s type system is working, that file access can still work, even while the caller has no other way to access files. Similarly, you can provide a png library with callbacks that grab data from a file, without it being able to access files itself.
All of the access to libraries and similar is through
mod and therefore, I’m suggesting restriction attributes on
mod that would restrict what further sub-modules a module can load, with an easy way of saying ‘only the known-safe ones’. So your main module could import what it likes, but it could restrict sub-modules to importing only specific things. The current Rust type system would take care of the rest.
It’s worth noting that
#![no_std] actually goes some way towards this, but eliminates a number of useful base libraries. Splitting std exports just a little could facilitate both better embedded programming and this proposed new feature.
Those who don’t care about any of this could just continue importing all of std and carry on as normal. It only restricts those who choose to have the extra safety.