Huh? What is it you think Rust copied here? I agree that the choice in C++ is essentially worthless, so that in practice you can write functions which are definitely never executed at compile time and aren't constant in any sense, label them constexpr and that compiles anyway. It just becomes yet more noise C++ programmers learn to type by reflex to get the correct behaviour from their compiler, joining explicit.
But in Rust that's not what you're getting. Rust's const fn is none of the options C++ decided it needed, Rust says if the parameters are themselves constants then we promise we can evaluate this at compile time and if appropriate we will -- this means we can use Rust's const fn where we'd use C++ consteval, but the function can also be called at runtime with variable parameters - and we can use Rust's const where we'd use C++ constinit, calling these const fn with constant parameters.
Because Rust is more explicit about safety of course, we can often get away with claiming some value is "constant" in C++ despite actually figuring out what it is at runtime, and Rust isn't OK with that, for example in my code
const OVERSIZE: u32 = SIG_BITS.next_power_of_two() << 1;
We can just calculate what power of two is bigger than SIG_BITS and shift it left at compile time. But...
pub(super) static SHORT_80: LazyLock<Rational> = LazyLock::new(|| Rational::fraction(1, 80).unwrap());
The Rational type is a big rational, it owns heap allocations so we'll just make one once, at runtime, and then re-use it whenever we need this particular fraction (it's for calculating natural logarithms of arbitrary computable real numbers).