L'évaluation constante en Rust permet d'exécuter certaines parties des calculs ou de l'initialisation à l'étape de compilation, plutôt qu'au moment de l'exécution du programme.
const PI: f64 = 3.1415;
static mut GLOBAL_COUNTER: i32 = 0;
const fn est une fonction dont le résultat peut être utilisé pour définir une valeur const ou static. Ces fonctions peuvent être appelées dans un contexte constant.
const fn factorial(n: usize) -> usize { if n == 0 { 1 } else { n * factorial(n - 1) } } const FACT_5: usize = factorial(5); // Se compile !
Limitations de const fn :
Box::new et autres),Question : Peut-on utiliser n'importe quelle fonction dans un contexte const, si son résultat ne change pas ? Par exemple, comme ça :
fn add(a: i32, b: i32) -> i32 { a + b } const RES: i32 = add(1, 2);
Réponse fausse typique : Oui, car la fonction est pure et le résultat est connu à l'avance.
Réponse correcte : Non, la fonction doit être explicitement déclarée comme const fn, seulement alors elle peut être appelée dans une initialisation const. Les fonctions ordinaires ne sont appelées qu'à l'étape d'exécution !
Exemple :
const fn add(a: i32, b: i32) -> i32 { a + b } const RES: i32 = add(1, 2); // Se compile !
Histoire
Dans un projet avec des calculs de géométrie 3D, un développeur a essayé de déclarer un tableau de valeurs en utilisant le résultat d'un appel à une fonction ordinaire, plutôt qu'une const fn. En conséquence, des erreurs de compilation sont apparues, et le profit du calcul à l'étape de compilation a été perdu.
Histoire
L'utilisation de static mut pour un cache global a conduit à une concurrence de données lors des accès depuis plusieurs threads (static mut n'est pas sûr !). Il aurait fallu utiliser Atomic ou Mutex pour synchroniser l'accès à la ressource globale.
Histoire
Dans une tentative d'accélérer l'initialisation de grands tableaux, ceux-ci ont été définis comme static, mais on a oublié que static a toujours une adresse fixe, ce qui a empêché les données d'être mises en cache par le processeur comme local, et les opérations se sont ralenties sur le chemin chaud de la logique du serveur. Il aurait fallu utiliser des expressions let locales avec des calculs à l'exécution.