Avec une sortie prévue fin 2017, Swift 4.0 vise à stabiliser le langage, à la fois au niveau du code source et de l'ABI. Les nouvelles fonctionnalités intégreront des améliorations génériques et un modèle de gestion de la mémoire inspirée de Rust/Cyclone.
Le développement de Swift 4 se divise en deux étapes. La première inclura toutes les fonctionnalités requises pour stabiliser l'ABI de Swift tout en garantissant la compatibilité des sources avec Swift 3. La seconde étape, qui est encore à définir, devrait également inclure de nouvelles fonctionnalités, à la fois importantes et petites, tant qu'elles ne modifient pas l'ABI ou des fonctionnalités existantes ou qu'elles ne cassent l'ABI sur la "standard library".
Compatibilité de source
L'exigence sur la compatibilité de source est fondamentale, bien qu'une stabilité du langage puisse limiter sa capacité à évoluer. Pour favoriser une évolution rapide du langage tout en garantissant la compatibilité, l'équipe Swift étendra l'attribut actuel @available
pour indiquer la disponibilité d'une fonctionnalité, non seulement par rapport à une plateforme particulière ou une version d'OS, mais aussi par rapport à une version du langage.
Par exemple, voici la manière dont vous pourriez déclarer une API qui est obsolète en Swift 3.1 :
@available(swift, obsoleted: 3.1)
class Foo {
//...
}
Stabilité de l'ABI
La stabilisation de l'ABI Swift demandera d'un côté la mise à disposition des bases pour les nouvelles fonctionnalités à ajouter, dont une appelée résilience, qui mettra à disposition une manière pour les API publiques d'évoluer en garantissant la stabilité de l'ABI. Ceci pourra se faire, par exemple, en explicitant les aspects des API pouvant changer sans casser l'ABI, et donc éliminer le problème de classe fragile qui apparaît dans certains langages orientés objet.
De l'autre côté, la stabilisation de l'ABI impliquera le nettoyage de déficiences du langage pour qu'elles ne se pérennisent pas dans l'ABI. Parmi les améliorations identifiées :
- Les conformités conditionnelles, qui expriment la notion qu'un type générique se conformera à un protocole spécifique seulement lorsque ses arguments type répondent à certaines exigences. Parmi les exemples disponibles, la collection
Array
qui implémente le protocoleEquatable
seulement si ses éléments sont desEquatable
:
extension Array: Equatable where Element: Equatable {
static func ==(lhs: Array<Element>, rhs: Array<Element>) -> Bool { ... }
}
- Les exigences de protocoles récursifs, qui permettent pour un type associé d'être conforme à un protocole d'encapsulation. Par exemple, une
Subsequence
devrait être lui-même uneSequence
, d'où Swift 4 permettra la définition suivante, pour le moment mal formé :
protocol Sequence {
associatedtype Iterator : IteratorProtocol
...
associatedtype SubSequence : Sequence // currently ill-formed, but should be possible
- Des clauses
where
pour les types associés, qui apporteront la puissance du termewhere
, déjà disponibles avec des paramètres de type générique vers les types associés. Par exemple :
protocol Sequence {
associatedtype Iterator : IteratorProtocol
associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Element
Enfin, un gros morceau du travail s'orientera sur la définition d'un modèle de gestion de la mémoire inspiré de Cyclone et Rust. La gestion de mémoire de Rust est construite sur le concept d'ownership (propriété) d'une entité, qui peut être déplacé ou emprunté pour suivre qui en est responsable pour la désallocation et qui peut l'utiliser. Ceci se couple avec la notion de cycle de vie pour éviter des références perdues (dangling) quand une entité est finalement désallouée. Le dialecte C Cyclone, qui n'est plus aujourd'hui en phase de développement, utilise un modèle de gestion de la mémoire par région, où chaque entité allouée est assignée à une région pour améliorer la (dés)allocation de performance et mieux suivre la détection des désallocations d'entités. L'extension du modèle de gestion de la mémoire de Swift sera particulièrement utile pour les développeurs système et dans tous les cas quand la détermination des performances est hautement désirable. Cet effort s'étendra probablement au delà des limites de l'étape 1, où l'objectif est d'avoir un design global pour comprendre la manière dont évoluera l'ABI.