Salut,
Ces trucs s’appellent des attributs, et servent à parler au compilateur et outils de développement pour indiquer des choses variées. Je t’invite à consulter la référence pour avoir une idée de tout ce qu’on peut faire avec. Les usages les plus courants sont
- marquer une fonction comme étant un test
#[test]
, et ne compiler certaines parties du code que lorsqu’on est en train de faire les tests #[cfg(test)]
;
- automatiquement implémenter certains traits, avec par exemple
#[derive(Clone)]
;
- localement changer les diagnostics compilateurs (par exemple
#[allow(unused)]
) ou de clippy (comme #![warn(clippy::pedantic)]
).
Il y a d’autres usages plus ou moins communs selon le genre de logiciel que tu développes, par exemple marquer une fonction comme un bon candidat pour l'inlining avec #[inline]
, ou encore activer localement certaines fonctionnalités propres à certaines architectures de processeurs comme #[target_feature(enable = "avx2")]
. C’est déjà beaucoup plus spécifique et rare comme usage, mais tu peux croiser des choses de ce genre dans la lib standard par exemple.
Et dernière chose, #[...]
et #![...]
sont très similaires : le premier s’applique à l’élément qui suit l’attribut, et le second à l’élément dans lequel l’attribut existe. Donc
#[allow(unused)]
fn foo(bar: u8) {}
et
fn foo(bar: u8) {
#![allow(unused)]
}
sont la même chose. La seconde forme est peu utilisée en pratique. En général, #![...]
est réservé aux attributs d’un module situé à la racine d’un fichier, et aux attributs "globaux" à lib.rs
.