Every crate in Rust is opt-in, that is, you need to explicitly ask it as a dependency to have it as a dependency of your code (usually through Cargo.toml
). All, but one: the standard library (hence the name), which is opt-out. That is to say, if you do nothing, Rust will implicitly understand you require it as a dependency, and you explicitly need to tell it that you don't (with #![no_std]
) to prevent this. Besides this, std
behaves like any other crate, that is, even if it's not one of your direct dependencies, you can still access to reexports of your actual dependencies.
It should be noted, however, that there is no reason to not want to standard library as a dependency except in situations where you just don't have it (for instance, if you are writing embedded code, or a kernel, or ...). In this case, having std
as a (transitive) dependency will just fail at compile time, which means that not only you have to use #[no_std]
, but so should all the dependencies you have, and their dependencies, and so on... In your case, you have annotated your code with #[no_std]
, but there was no hard requirement for you to do so, so there is no problem in having a dependency that has access to std
.
Finally, note that some parts of the standard library are accessible even if the whole standard library is not. For instance, core
is not OS-dependent, so you can use it even on embedded, and usually obtaining alloc
one way or another (that is, implementing what is required yourself for instance) also provides you quite a lot of the standard library. In particular, I think HashSet
only requires core
and alloc
to be available, not the whole standard library.