Rust 1.39.0 sonne l'arrivée en version stable des fonctions async,
et la possibilité de placer des attributs dans les paramètres des fonctions

L'équipe responsable du développement de Rust a annoncé la disponibilité de Rust 1.39.0. Voici quelques points importants.

L'.await (attente) est terminée, dites bonjour aux async fn

Dans Rust 1.36,le trait Future a été proposé en version stable. L'équipe espérait donner aux « crate » importants, aux bibliothèques et à l'écosystème le temps de se préparer à async / .await.

Il aura fallu attendre l'arrivée de Rust 1.39 pour mettre un terme à cette attente. En effet, à partir de cette version, async / .await est désormais proposé en version stable. Concrètement, cela signifie que vous pouvez désormais définir des fonctions et blocs async et les mettre en .await.

Une fonction async, que vous pouvez annoncer en écrivant async fn au lieu de fn, ne fait rien d'autre que retourner un Future lorsqu'elle est appelée. Ce Future est un calcul suspendu que vous pouvez conduire à son terme en le mettant en .await. Outre async fn figurent les blocs async { ... } et async move { ... }, qui agissent comme des fermetures et peuvent être utilisés pour définir des "littéraux asynchrones".

Nom : rust.jpg
Affichages : 13272
Taille : 13,7 Ko

En somme, Async-wait est un moyen d'écrire des fonctions qui peuvent "mettre en pause", rendre le contrôle au runtime, puis reprendre à l'endroit où elles se sont arrêtées. Généralement, ces pauses doivent attendre les E / S, mais il peut y avoir un grand nombre d'utilisations. Vous connaissez peut-être l’async-wait de JavaScript ou C #. La version de Rust de la fonctionnalité est similaire, mais avec quelques différences clés.

Pour vous en servir, commencez par écrire async fn au lieu de fn
Code Rust : Sélectionner tout - Visualiser dans une fenêtre à part
async fn first_function() -> u32 { .. }

Contrairement aux fonctions régulières, appeler une async fn n'a pas d'effet immédiat. Au lieu de cela, elle retourne Future, une opération suspendue qui attend d'être exécutée. C'est l'opérateur .await qui va lancer son exécution :

Code Rust : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
async fn another_function() {
    // Create the future:
    let future = first_function();
 
    // Await the future, which will execute it (and suspend
    // this function if we encounter a need to wait for I/O): 
    let result: u32 = future.await;
    ...
}

Cet exemple montre la première différence entre Rust et d'autres langages : nous écrivons future.await au lieu de await future, une syntaxe qui s'imbrique mieux avec l'opérateur ? de Rust pour propager des erreurs (qui, après tout, sont très courantes dans les E / S). Vous pouvez simplement écrire future.await? pour attendre le résultat d'un futur et propager des erreurs.

Références aux liaisons dans match

Lors de la recherche de motif dans Rust, une variable, également appelée "liaison", peut être liée de la manière suivante:
  • par référence, immuablement ou mutuellement. Ceci peut être réalisé explicitement par exemple via ref my_var ou ref mut my_var respectivement. La plupart du temps cependant, le mode de liaison sera automatiquement déduit.
  • par valeur : soit par copie, lorsque le type de la variable liée implémente Copy, ou sinon par déplacement.

Auparavant, Rust interdisait de prendre des références partagées pour des liaisons par déplacement dans les expressions if ou match, ce qui signifie que le code suivant aurait été rejeté :

Code Rust : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fn main() {
    let array: Box<[u8; 4]> = Box::new([1, 2, 3, 4]);
 
    match array {
        nums
//      ---- `nums` is bound by move.
            if nums.iter().sum::<u8>() == 10
//                 ^------ `.iter()` implicitly takes a reference to `nums`.
        => {
            drop(nums);
//          ----------- `nums` was bound by move and so we have ownership.
        }
        _ => unreachable!(),
    }
}

Avec Rust 1.39.0, l'extrait de code ci-dessus est maintenant accepté par le compilateur. L'équipe espère que cela donnera une expérience plus lisse et plus cohérente avec les expressions match en général.

Attributs sur les paramètres de fonction

Avec Rust 1.39.0, les attributs sont désormais autorisés dans les paramètres des fonctions, des fermetures et des pointeurs de fonction. Alors qu'avant, vous auriez peut-être écrit:

Code Rust : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
#[cfg(windows)]
fn len(slice: &[u16]) -> usize {
    slice.len()
}
#[cfg(not(windows))] 
fn len(slice: &[u8]) -> usize {
    slice.len()
}

Vous pouvez désormais écrire plus succinctement

Code Rust : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
fn len(
    #[cfg(windows)] slice: &[u16], // This parameter is used on Windows.
    #[cfg(not(windows))] slice: &[u8], // Elsewhere, this one is used.
) -> usize {
    slice.len()
}

Les attributs que vous pouvez utiliser dans cette position incluent :
  1. Compilation conditionnelle: cfg et cfg_attr
  2. Les contrôles allow, warn, deny, et forbid
  3. LEs attributs auxiliaires utilisés par les attributs de macro procéduraux appliqués aux éléments.

Source : Rust