Cache intermediate results in const-generic function (using interior mutability)

⚓ rust    📅 2025-06-10    👤 surdeus    👁️ 4      

surdeus

I'm working on a performance critical section of my code. I want to cache some intermediate results that only rely on the size of the input, not the input itself. I'm using a const OnceLock for the caching. I'm running into a clippy warning that I'm not sure is fine to suppress.

The function in question is an internal helper function. I control all the call sites of the function. The part relevant to caching can be summarized as:

fn compute_something<const INPUT_LEN: usize>(input: _) {
    const FOO: OnceLock<_>= OnceLock::new();
    let foo = FOO.get_or_init(|| /* uses INPUT_LEN */);
    /* rest of the computation */
}

The relevant warning is declare_interior_mutable_const. In its help section, two solutions are proposed: using a static item over the const, or turning the (surrounding?) function into a const fn in order to communicate to the call site that a new const is being created. statics don't do what I want, since I want one const per call site, not one static shared across monomorphizations of the function (playground):

use std::sync::OnceLock;

fn main() {
    assert_eq!(0, use_static::<0>());
    assert_eq!(1, use_static::<1>()); // assertion failed; left: 1, right: 0
}

fn use_static<const X: usize>() -> usize {
    static FOO: OnceLock<usize>= OnceLock::new();
    *FOO.get_or_init(|| /* crunch numbers*/ X)
}

I'm not sure what the second part of the advice means. Should I turn my compute_something function into a const fn? That might be possible somehow, but other things are happening in there, and those things don't need to be const (for any other reason). Is the advice to factor out the const FOO into a new const fn? If so, how does that change anything?

The lint's description lists some cases in which using a const with interior mutability is fine, but I'm not sure any of those apply to my case. I'm using the latest stable version, so “prior to const fn stabilization” does not apply. The other exception, “types which contain private fields with interior mutability”, seemingly also does not apply, as the const is not a field on a type. Is my case spiritually identical to the latter exception?

Is there a “more correct” approach to this kind of caching than what I'm currently doing?

1 post - 1 participant

Read full topic

🏷️ rust_feed