Kotlin 1.6.20

Par:
fredericmazue

ven, 08/04/2022 - 12:19

JetBrains a publié Kotlin 1.6.20. Cette version apporte 2 nouveautés notables au langage et de nombreuses améliorations de performances.

La première nouveauté de Kotlin 1.6.20 au niveau du langage est le 'Prototype de récepteurs de contexte'. Avec Kotlin 1.6.20, vous n'êtes plus limité à un seul récepteur. Si vous avez besoin de plus, vous pouvez rendre les fonctions, les propriétés et les classes dépendantes du contexte (ou contextual ) en ajoutant des récepteurs de contexte à leur déclaration. Par exemple :

interface LoggingContext {
    val log: Logger // This context provides a reference to a logger
}

context(LoggingContext)
fun startBusinessOperation() {
    // You can access the log property since LoggingContext is an implicit receiver
    log.info("Operation has started")
}

fun test(loggingContext: LoggingContext) {
    with(loggingContext) {
        // You need to have LoggingContext in a scope as an implicit receiver
        // to call startBusinessOperation()
        startBusinessOperation()
    }
}

Une déclaration contextuelle exige que tous les récepteurs de contexte déclarés soient présents dans la portée d'un appelant en tant que récepteurs implicites et apporte les récepteurs de contexte déclarés dans sa portée de corps en tant que récepteurs implicites. Pour activer les récepteurs de contexte dans votre projet, utilisez l'option -Xcontext-receivers du compilateur. 

Les 'Types définitivement non nullables' sont l'autre nouvauté majeure du langage. Pour fournir une meilleure interopérabilité lors de l'extension des classes et des interfaces Java génériques, Kotlin 1.6.20 vous permet de marquer un paramètre de type générique comme définitivement non nullable avec la nouvelle syntaxe T & Any. Par exemple :

fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y

fun main() {
    // OK
    elvisLike<String>("", "").length
    // Error: 'null' cannot be a value of a non-null type
    elvisLike<String>("", null).length
 
   // OK
    elvisLike<String?>(null, "").length
    // Error: 'null' cannot be a value of a non-null type
    elvisLike<String?>(null, null).length
}

Remarque : il faut positionner la version linguistique sur 1.7 pour activer cette fonctuonnalité

Kotlin 1.6.20, c'est aussi de nombreuses améliorations de performances. Tout d'abord, JetBrains a travaillé à améliorer le temps de compilation du nouveau backend JVM IR.  Ainsi a été ajouté le mode backend expérimental JVM IR pour compiler tous les fichiers d'un module en parallèle. La compilation parallèle peut réduire le temps total de compilation jusqu'à 15%, selon JetBrains. L'éditeur précise que cette parallélisation n'est utile que lorsque la construction du projet n'est pas suffisamment parallélisée par un outil de construction tel que Gradle. En revanche, si un projet se compose de nombreux petits modules et a déjà une construction parallélisée, l'ajout d'une autre couche de parallélisation peut nuire aux performances.

Arrive aussi un nouveau mode de compilation incrémentale. Dans ce mode, le compilateur met en cache les résultats des compilations précédentes au niveau du module. Il utilise ensuite les résultats de compilation mis en cache pour les fichiers source inchangés lors des compilations suivantes, ce qui les rend les opérations plus rapides, en particulier dans le cas de petites modifications.

Enfin, Jetbrains travaille à améliorer les performances de Kotlin/Native. Ainsi, Kotlin 1.6.20 M1 apporte des mises à jour de performances qui affectent le LLVM IR généré. Selon les benchmarks de JetBrains, les gains moyens de performances sont les suivants :

  • 15% de réduction du temps d'exécution
  • Réduction de 20 % de la taille du code des binaires de version et de débogage
  • Réduction de 26 % du temps de compilation des binaires de publication

Toujours selon JetBrains, ces améliorations permettent également de réduire de 10% le temps de compilation d'un binaire de débogage sur un grand projet.

Enfin nous remarquons la prise en charge des exécutables Android autonomes. Auparavant, les exécutables Android Native dans Kotlin/Native n'étaient pas réellement des exécutables mais des bibliothèques partagées que vous pouviez utiliser comme NativeActivity. Il existe désormais une option permettant de générer des exécutables standard pour les cibles Android natives.

Pour cela, dans la partie build.gradle(.kts) de votre projet, configurez le bloc exécutable de votre cible androidNative. Ajoutez l'option binaire suivante :

kotlin {
    androidNativeX64("android") {
        binaries {
            executable {
                binaryOptions["androidProgramType"] = "standalone"
            }
        }
    }
}

Cette fonctionnalité deviendra la valeur par défaut dans Kotlin 1.7.0.