Reputation: 14318
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
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
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