Open EFanZh opened 9 months ago
Array repeat expressions are not guaranteed to be consts, e.g. this is valid:
use atomic::Ordering;
use core::sync::atomic::AtomicU32;
static CNT: AtomicU32 = AtomicU32::new(0);
fn foo() -> u32 {
CNT.fetch_add(1, Ordering::Relaxed)
}
fn main() {
let _a = &[foo(); 32];
}
You can either use a separate const as in your 2nd example or (on nightly) you can use inline consts
#![feature(inline_const)]
pub fn test(f: fn(&[u32; 10])) {
f(&[const { std::convert::identity(7) }; 10]);
f(&[const { std::convert::identity(7) }; 10]);
f(&[const { std::convert::identity(7) }; 10]);
f(&[const { std::convert::identity(7) }; 10]);
}
Array repeat expressions are not guaranteed to be consts
If a value can’t be determined at compile time, it is understandable that the compiler can’t do the optimization. The problem is that there might be an optimization opportunity if the value can indeed be determined at compile time, which the compiler failed to utilize.
you can use inline consts
Even if inline consts was stabilized, there are expressions that can’t be enclosed in const blocks, but still generates compile time const values (like std::panic::Location::caller
).
The problem is originated from https://github.com/rust-lang/log/pull/599.
Sometimes, multiple function calls can have the same constant arguments:
Rust recognizes that these arguments are the same value, so it would create a single constant value and pass it to each function:
But sometimes, these constant arguments have to be computed by some additional functions:
Then the compiler can’t optimize these constant objects well as the first example, additional copying operations are generated:
You can see the comparison here: https://godbolt.org/z/frj9a8TG6.
Additionally, using a const value as a proxy helps:
But some functions can’t be used to compute a const value, such as
std::panic::Location::caller
, so the method above does not always work.