RustCrypto / traits

Collection of cryptography-related traits
594 stars 194 forks source link

Make `output_size()` a `const fn` #1574

Closed jmg-duarte closed 6 months ago

jmg-duarte commented 6 months ago

I am trying to write the following function:

fn generate_single_width_index<H>(count: usize) -> SingleWidthIndex
where
    H: Digest,
{
    let mut entries = vec![];
    for idx in 0..5 {
        let mut data = [0u8; <H as Digest>::output_size()];
        rand::thread_rng().fill(&mut data);
        let digest = H::digest(data).to_vec();
        entries.push(IndexEntry {
            digest,
            offset: idx,
        });
    }
    SingleWidthIndex::try_from(entries).unwrap()
}

But I get the following error:

error[E0015]: cannot call non-const fn `<H as Digest>::output_size` in constants
   --> storage/file-storage/src/car/v2/index.rs:451:34
    |
451 |             let mut data = [0u8; <H as Digest>::output_size()];
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants

Before anything else, I know Digest is not from this crate, but — Digest: OutputSizeUser — which is where output_size is defined.

Since the output_size is supposed to be known at compile time, making it const fn not only makes sense but would also solve this issue.

Note: I know I can make data a Vec and solve the issue that way.

newpavlov commented 6 months ago

Functions in traits cannot be const in the current stable version of Rust. Instead of output_size you could write <H as OutputSizeUser>::OutputSize::USIZE, but note that you will not be able to use this constant to create an array because of limitations of the const genercis system.

For now, I would recommend to use GenericArray in your generic code. In future crate versions we will use hybrid-array which should make retrieval of byte array a bit easier.