Skip to content

Tracking Issue for Hasher::{write_str, write_length_prefix} (feature(hasher_prefixfree_extras)) #96762

Open

Description

@scottmcm

Feature gate: #![feature(hasher_prefixfree_extras)]

This is a tracking issue for the new provided methods on Hasher added to fix #94026

  • write_str lets the hasher customize how it works with str, so it can use the b'\xFF' trick if it's byte-wise, or a different approach if it does chunked rounds.
  • write_length_prefix gives an obvious choice when implementing Hash for collections (like VecDeque) which can't just use the slice hash, and allows the hasher to optimize how best to represent the length.

Public API

// core::hash

pub trait Hasher {
    // ... existing stuff ...
    fn write_length_prefix(&mut self, len: usize);
    fn write_str(&mut self, s: &str);
}

Steps / History

Unresolved Questions

  • What should the write_str provided implementation be? It was added matching the previous impl Hash for str behaviour to get in without breaking hash checks (like the one in cargo), but that's not always prefix-free (it depends on the round strategy), so there's an argument that a different implementation would be better.

Activity

  1. added
    T-libs-api[DEPRECATED; DO NOT USE]
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on May 6, 2022
  2. tgross35 commented on Apr 10, 2024

    @tgross35
    Member

    Possible bikeshed: it was indirectly mentioned in passing here that this is the only std API that comes up when you search length. The rest all seem to use len

  3. hoxxep commented on May 17, 2025

    @hoxxep

    Author of the rapidhash crate here, I'm wondering how to go about pushing this towards stabilisation?

    Being able to omit the separate 0xFF write call when hashing strings would be a helpful performance boost in block-based hashing algorithms that already reseed using the byte length on every .write(&[u8]) call. Thanks!

  4. ChrisDenton commented on May 22, 2025

    @ChrisDenton
    Member

    See the stabilization process docs: https://std-dev-guide.rust-lang.org/development/stabilization.html#stabilization-report. Essentially write a stabilization report detailing what is being stabalized and why.

    I see one "unresolved question" in the OP. That will probably need to be resolved one way or another.

  5. hoxxep commented on Jul 27, 2025

    @hoxxep

    Linking a relevant PR and discussion about write_str's default behaviour and alternate suggestions: #134134 (comment)

    Key points:

    • There was a suggestion to also include a write_bytes method, similar to write_str. This would move the write_length_prefix call out of the impl<T> Hash for [T] and into the Hash::hash_slice method. This would allow the unpadded numeric slices to override hash_slice to call write_bytes and give hashers like foldhash and rapidhash the chance to omit the unnecessary write_length_prefix call for byte slices for their algos.
    • For a DoS resistant hasher, write_length_prefix can only ever really mean write_usize. However, it's still useful to include, as non-DoS resistant hashers can omit the length prefix, but wouldn't want to omit hashing usize fields.
    • Any changes to the default behaviour of write_str (or the inclusion of write_bytes) would break the hash output stability of Hash::hash between compiler versions. This isn't necessarily a problem, the std library doesn't promise stability. This would however be the first major breaking change to Hash::hash output stability, and I'm aware there are many users who currently abuse the standard library types for portable hashing that are blissfully unaware.

    I am currently trialling write_bytes in an experimental portable-hash crate as an example, with the intention of offering PortableHash and PortableHasher traits to make it easier for users to maintain hash output stability between platforms and compiler versions.

  6. peter-lyons-kehl commented on Sep 7, 2025

    @peter-lyons-kehl
    Contributor

    Thank you so much for hasher_prefixfree_extras. I have a different use case for this (extra signalling protocol between select types being hashed and a custom Hasher adapter; I'll share more once it's usable).

    write_str ... breaking hash checks (like the one in cargo)

    • Could someone elaborate, give an example or point to the offended/upset code?
    • Do I understand right that cargo stores/depends on hash values? If that's what cargo does, then they could write their own Hasher implementation/adapter using the existing/legacy code, or find some other way to workaround. It's clearly against https://doc.rust-lang.org/nightly/core/hash/trait.Hash.html#portability:
      • "data passed by most standard library types should not be considered stable between compiler versions."
      • "This means tests shouldn’t probe hard-coded hash values or data fed to a Hasher and instead should check consistency with Eq."
      • "Serialization...should either avoid encoding hashes or only rely on Hash and Hasher implementations that provide additional guarantees"
      • If cargo uses HashMap with RandomState (its default BuildHasher), that uses DefaultHasher, whose "internal algorithm is not specified, and so it and its hashes should not be relied upon over releases."
  7. clarfonthey commented on Nov 14, 2025

    @clarfonthey
    Contributor

    Poking around here since I'd like these:

    Right now, I think that write_str should be kept, but write_string_suffix should be added to replace calls to write_str(""). Essentially, for now, write_u8(0xFF) is relying a bit too much on the internals of strings for taste, and it would be better to be able to easily match libstd string hashing behaviour without just using a magic number.

    I think it would be reasonable, if libstd wants to commit to slices and strings hashing differently, to have a dedicated write_string_suffix method to replace a call to write_u8(0xFF) as needed, or to eliminate it altogether and require write_length_prefix instead.

  8. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    T-libs-api[DEPRECATED; DO NOT USE]
    on Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCS-tracking-needs-to-bakeStatus: The implementation is "complete" but it needs time to bake.T-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions