Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Types et inférence

Rust est un langage au typage statique et fort. Cela signifie que le compilateur doit connaître le type de chaque variable à la compilation.

Cependant, grâce à l’inférence de types, nous n’avons pas besoin de tout écrire manuellement : le compilateur devine le type des littéraux et de nos variables dans la grande majorité des cas.

Attention toutefois aux raccourcis de fainéantise et de négligence. Il est souvent préférable d’indiquer clairement le type souhaité au compilateur plutôt que de le laisser appliquer ses types par défaut.

L’Inférence de Types en Action

Le compilateur analyse comment une variable est utilisée pour en déduire son type. Dans la mesure où il contrôle tous les types dans l’ensemble du code, il infère tous les littéraux et toutes les variables et expressions dont nous n’avons pas précisé le type explicitement.

Si plusieurs types sont possibles, nous pouvons (et devrions) orienter le choix en ajoutant une annotation de type.

fn main() {
    // Le compilateur inférerait automatiquement le type `i32` 
    // (entier signé sur 32 bits par défaut)
    // Âge ne peut pas être négatif ni très grand 
    // => nous orientons.
    let age: u8 = 30; 

    // Annotation explicite requise ici car `parse()` 
    // peut retourner plusieurs types numériques
    let score: u8 = "42".parse().expect("Pas un nombre valide");
    
    println!("Age: {age}, Score: {score}");
}

Types Scalaires

Un type scalaire représente une valeur unique. Rust en possède quatre principaux : les entiers, les flottants, les booléens et les caractères.

Les entiers (integers)

Ils se déclinent selon leur taille (en bits) et leur nature (signés i ou non signés u).

TailleSignéNon Signé
8 bitsi8u8
16 bitsi16u16
32 bitsi32 (défaut)u32
64 bitsi64u64
128 bitsi128u128
Architectureisizeusize (indexation)
fn main() {
    let un_octet: u8 = 255;
    let indice: usize = 10; // Dépend de l'architecture (32 ou 64 bits)
}

Les nombres à virgule flottante (floats)

Rust gère le f32 (simple précision) et le f64 (double précision, choix par défaut).

fn main() {
    let pi = 3.14159; // f64 par défaut
    let rating: f32 = 4.5;
}

3. Le Type Booléen

Le type bool prend deux valeurs possibles : true ou false.

fn main() {
    let est_valide = true;
    let acces_refuse: bool = false;
}

4. Le Type Caractère

Le type char représente un scalaire Unicode. Il fait 4 octets et se délimite par des simples quotes ('). Il peut stocker un accent, un emoji ou un caractère asiatique.

fn main() {
    let lettre = 'A';
    let emoji = '🦀'; // Totalement valide
}

Types Composés

Les types composés permettent de regrouper plusieurs valeurs dans un seul type. Rust en propose deux principaux : les tuples et les tableaux.

1. Les Tuples

Un tuple regroupe des valeurs de types différents. Sa taille est fixe à la déclaration.

fn main() {
    // Déclaration et annotation optionnelle
    let developpeur: (&str, u8, bool) = ("Alice", 28, true);

    // Accès direct par indexation avec un point
    let nom = developpeur.0;
    let age = developpeur.1;

    // Décomposition (Destructuring)
    let (name, age_exact, _) = developpeur;
    
    println!("{name} a {age_exact} ans.");
}

2. Les Tableaux (Arrays)

Un tableau regroupe des valeurs du même type. Sa taille est fixe et connue dès la compilation. Les données sont stockées de manière contiguë sur la pile (stack).

fn main() {
    // Déclaration classique
    let calendrier = [1, 2, 3, 4, 5];

    // Spécification : [type; taille]
    let octets: [u8; 3] = [0, 128, 255];

    // Initialisation rapide avec une valeur répétée : [valeur; nombre]
    let tampon = [0; 512]; // Un tableau de 512 zéros

    // Accès aux éléments (commence à 0)
    let premier = calendrier[0];
    
    // ATTENTION : Rust vérifie les limites à l'exécution.
    // let hors_limite = calendrier[10]; // Provoque un panic à l'exécution
}
Annotations de type

J’ai regroupé les différentes manières d’annoter des types dans : Annotations de types.