Why is the str datatype in rust declared in three different spaces?

the str datatype in rust is defined in alloc and std and core why what is the purpose ?

std : std - Rust

core : core - Rust

alloc : alloc - Rust

They are the exact same thing.

3 Likes

If we want to get technical, str is "declared" in the compiler, because it's a primitive type.

The standard library is split between core, alloc, and std to coarsely represent different runtime support levels that targets can have. core is essentially target agnostic functionality[1], alloc adds the concept of global dynamic heap allocation, and std adds functionality that interacts with the host OS environment.

So that most users of std don't have to think about this split, std reexports everything from core (think pub use) and uses #[doc(inline)] to present the documentation as-if it were defined inline instead of in a separate crate. There are also some rustc-specific exceptions to coherence checks that allow the three crates to pretend they're one for the purpose of conference (being allowed to write impls for locally defined types that you can't write for upstream types).

You can confirm that they're the same type because you can assign from a variable of type &core::primitive::str to one of type &std::primitive::str, and similarly for the other core/alloc names reexported from std.

This is generally referred to as the "std facade[2]," and there's a long-running initiative to eventually reach "std reunification" where std is defined more like a library crate with feature flags than the current setup.

Other ecosystem crates on crates-io sometimes use a similar layered facade approach to split the implementation over multiple crates[3]; notable examples include futures and bevy. More common than the many-crate approach is a two-crate split with a "core" and "full" API such as used by rand and rand_core (and I suppose getrandom could be included in this family).


  1. Caveat: some things like core::arch and core::atomic are only conditionally available based on architecture support. ↩ī¸Ž

  2. noun: facade; an outward appearance that is maintained to conceal a less pleasant or creditable reality. ↩ī¸Ž

  3. This can have benefits to compile time (if the crate dependency graph is wide, it enables further parallelism) and for crates that only need a subset of functionality to only depend on that subset, even if the entire package is included into the build tree (which allows better build pipelining by not waiting on building functionality a library doesn't need as well as core types being versioned more stably than the veneer) ↩ī¸Ž

9 Likes

Closed as a duplicate of

2 Likes