Zebrafish
Zebrafish

Reputation: 14318

Why isn't HashMap::new in Rust const given it doesn't allocate?

My understanding is that neither Vec nor HashMap allocate for an empty container. Given that it doesn't allocate the ::new function can be const, right? This is the case for Vec, but not for HashMap. Why is this?

static my_vec: Vec<u32> = Vec::new(); // WORKS
static LIMIT_STRINGS: HashMap<String, u32> = HashMap::new(); // new() is not const

And so for the Hashmap we must use LazyLock?

Upvotes: 0

Views: 87

Answers (2)

metatoaster
metatoaster

Reputation: 18938

The new function defined simply calls Default::default() as of 1.84.1. The Default::default() cannot be a const fn is explained succinctly in this answer and the example used (non-deterministic seeding of a random number generator) applies directly to this question as the default HashMap::new is designed to have some protection against HashDoS by making use of a random seed at construction. In short, functions returning some random value per execution makes it not possible to provide that as a const fn (relevant thread on the Rust user forum, plus another related SO Q&A).

As explained by the other answer, the other construction method that uses const fn may be used, but be mindful that may result in a fixed hash per key which may result in HashDos type vulnerability in the resulting application, where its manifestation depends directly on the specific use case.

Upvotes: 2

Chayim Friedman
Chayim Friedman

Reputation: 71430

HashMap uses an Random Number Generator (RNG) seeded by the OS on creation, for protection against HashDoS attacks, so it cannot be built at compile time.

hashbrown, which is the crate that powers std's HashMap, offers a const fn with_hasher(), for when you use a different hasher that is const-constructible. Within std this was just stabilized (for Rust 1.85.0).

Upvotes: 2

Related Questions