PSA for `std` Feature in `no_std` Libraries
Tl;dr: don't use #![cfg_attr(not(feature = "std"), no_std)] to have an std feature, always use:
#![no_std]
#[cfg(feature = "std")]
extern crate std;
Details:
I'm currently working on no_std support for the Bevy game engine (check out the tracking issue here if you're interested!). When I first started, I knew we'd need an std feature. After a quick bit of searching, this help discussion appeared to provide the cleanest solution for optionally making a crate no_std:
#![cfg_attr(not(feature = "std"), no_std)]
One line at the top of the crate, and (while wordy) it makes sense. If I don't have the std feature, then I'm no_std.
However, this has a side-effect that can make working with the alloc crate a massive pain: enabling or disabling the std feature changes the implicit prelude between std::prelude and core::prelude. This creates an inconsistency between the std and no_std parts of your library where, for example, you need to explicitly import alloc::format in some code, and don't in others.
Instead, if you declare your crate as unconditionally no_std, with a feature flag to include the std crate, you'll always have the core::prelude, making your code much more consistent between the two features.
#![no_std]
#[cfg(feature = "std")]
extern crate std;