I really like this idea. It makes adding support for limited environments much easier. One example where this would help greatly is with std features for crates.io crates. Right now, if you want to give compat for non-std environments, you need to add such a std feature and add a lot of (useless) boilerplate like use core as std or something, even if your entire codebase doesn’t use a single thing from std. Due to limitations with how cargo features work, if you are depending on a crate that has such a std feature, and you are adding additional functionality to that crate, you’d have to add an std feature of your own and make your std feature depend on it.
A good example for this would be the RustCrypto hashes crates that all depend on the digest crate. The digest crate itself has an optional std feature. But the hashes crates don’t expose their own std feature so you are forced to live without std support. This means missing impls for Read for example. Read more on this issue here. You can probably avoid it by depending on the digest crate yourself and turning on the std feature but that trick is more of a hack. With the new system this would be so much nicer.
Part of this could be alleviated by having a system like the one envisioned by @withoutboats, with opportunistic features. This would be as simple as adding a std and alloc cfg flags to rustc or cargo for targets where there is no std available. This would allow us to avoid the flawed cargo feature system. While the automatic features suggestion is great in itself, one can go further and unify everything into one std crate as then you won’t have to remember to do extern crate core as std; or something all the time. So the proposal put forth by @aturon is I think the best solution to this!
There are a few points I’d make though:
- Like @jmst said,
i128 can be implemented on every platform. The fact that it is not has nothing to do with missing support by the target hardware. Most hardware doesn’t support i128 natively. Instead, the people who wrote the backends didn’t focus their attention onto i128. So IMO instead of forcing users to use custom i128 polyfills, i128 should be implemented for every platform, either by convincing the backend developers that i128 is important, or by doing lowering and other operations ourselves. The second option is easier on the backend developers and allows us to target things like nvptx earlier in time so probably prefferable. There should be no target where users are required to use custom-made i128 libraries! I do not think that we ever should have a cfg on i128. Instead if someone adds a target to Rust they should either implement custom lowering or ensure the backend works. We shouldn’t make users suffer from LLVM bugs!
- This post is very vague about the portability lint itself, just like the actual RFC that introduced it was. The RFC that introduced it spent more time talking about irrelevant stuff like removing
std::os and moving its elements elsewhere. I’d love to talk about the design of the portability lint, especially how to enable it. IMO, this should be a Cargo.toml feature. You should be able to say “this crate supports no_std environments” inside Cargo.toml. I don’t think that categories are a good solution for this, instead I’d love if you say “this crate supports no_std, no_alloc environments”, the portability lint gets turned on automatically and can’t be turned off, even for targets that do have std and allocator support.
-
@scottmcm raises a good point I think that right now it is very easy to talk about
no_std and core and similar. We should develop new terminology that is just as convenient to use.