Yes, I know about this RFC, but I don’t think it’s the best approach either. I had in mind a more general solution which will encompass not only target features, but also other target parameters as well. The basic idea is to keep target restrictions context for all items (including modules and crates) and to allow for selected items to restrict this context even further. (i.e target restrictions will be cascade, sub-item can not be less restricted than its parent, e.g. crate) The next step is to check if all used items fit into restriction contexts. (i.e. it will be impossible to use sse4
intrinsic in the context without restriction on enabled sse4
target feature) And the last step is to introduce compile time and runtime dispatch macros (they will have to be the language built-ins) which will allow us to create more restricted sub-contexts:
// use runtime detection to select which arm to execute
let result = runtime_dispatch!(
(feature=("avx2" && "sse4.1")) => foo_avx2_sse41(),
(feature="sse2") => {
// e.g. here we can call SSE2 intrinsics safely
let c = _mm_add_epi64(a, b);
},
_ => foo(), // fallback function
);
// select one of the arms at compile time and inline it into the code
let result = compiletime_dispatch!(bar,
(os="linux", feature="aes") => bar_linux_aes(),
(os="linux") => { ... },
(os="windows") => bar_windows(),
_ => bar(), // fallback function
);
(this is just a rough draft)
Thus all intrinsics will be safe, but it will be impossible to use them without introducing appropriate restrictions to the context in which they will be used.
And of course this approach asks for integration with cargo
, so we will be able to specify in the Cargo.toml
that crate is e.g. for windows only, or unconditionally depends on some target features, etc. And by having this information we will be able to better work with [target.'cfg(..)'.dependencies]
, so compiler at compile time will not allow e.g. to use windows-only dependency for linux only application, or sse4
dependent crate in the application without either adding this restriction to the application Cargo.toml
or by providing some sort of fallback. And if crate will specify crate-level target restriction it will be compiled with the enabled features without requiring to use RUSTFLAGS.
This approach can be seen as a generalization of RFC 1868. I fully understand that this proposal is quite large overhaul of the currently existing #[cfg(..)]
based manual approach and will require significant internal changes. Also in the worst case scenario it could require addition of a SAT solver to the compiler to evaluate if item can be used in the given restriction context. (although I hope with some reasonable restrictions we will be able to proceed without it)
But nevertheless it’s how I, as a user, see Rust ideally should work with target parameters. While this description is quite messy, I hope that the main idea is more or less conveyed. I’ll try to write a more detailed pre-pre-RFC later.