Skip to main content

nova_rt_int_hash_seed

Function nova_rt_int_hash_seed 

Source
#[unsafe(no_mangle)]
pub extern "C" fn nova_rt_int_hash_seed() -> i64
Expand description

The per-process seed for std/core’s Int, Bool and Char hashing, XORed into the input before mix64 runs.

Nova code can recover this value in one call, since those Hash impls XOR it in: (0).hash() is mix64(0 ^ seed), which is mix64(seed), and mix64 is an invertible bijection. That is the same shape ("").hash() already has for the string seed, it follows from ADR 0005’s one-shot Hash returning a plain Int, and the gate claim already declines the adaptive attacker for whom it matters. What the seed buys is precomputation resistance. tests/runtime/hash.nova performs that recovery, to cancel the seed when it asserts mix64’s canonical vectors.

Nullary and takes no pointer, so it needs no unsafe. Plain "C", not "C-unwind": every caller is a compiled Nova frame — std/core’s three Hash impls, reached from user code — and crate::task::PollFn’s doc closes its constraint block by saying the permission "C-unwind" grants exists for that module’s Rust-side entry points, not for compiled Nova frames. task’s abort_with states the general form in its own doc: a generated frame carries no landing pads, no drop glue and no unwind table, so an unwind that passed through one would have to be resolved against a frame the unwinder has no description of.

The panic that would do it is real rather than hypothetical. get_or_init runs RandomState::new, which draws OS entropy on the first call, and std panics when that draw fails — unconditionally on Linux and on the getrandom/getentropy platforms, and under a debug_assert on current Windows. (0).hash() inside an async fn body puts that first call inside a generated poll function. Plain "C" escalates such an unwind to panic in a function that cannot unwind and aborts, making the prohibited case structurally impossible instead of resting on the panic not happening.

nova_rt_str_hash is the precedent this follows: it makes the same RandomState::new draw through the same OnceLock and is plain "C" too. The nullary readers in log and time use "C-unwind" at this same signature; that divergence is pre-existing, is not resolved here, and their panic profiles differ from this one’s. Earlier versions of this comment specified "C-unwind" by reasoning from those readers’ shape, which is the inference nova_rt_float_fixed’s doc warns against — a neighbouring family’s ABI is not an argument — and one of them went further and asserted that task’s rule was narrower than the module states. It is not.