I'm sorry but I'm getting very confused. The current versions of Swift are:
Swift 3.1: Latest version of Swift 3 under the Swift 3 compiler.
Swift 3.2: Swift 4 compiler under Swift 3 compatibility mode.
Swift 3.3: Swift 4.1 compiler under Swift 3 compatibility mode.
Swift 4.0: Swift 4 compiler
Swift 4.1: Swift 4.1 compiler
Confusion 1: I'm not sure anymore why versions 3.2 and 3.3 were created. Can somebody explain? Why wasn't a solution like the one in this proposal used to start with?
Some libraries want to support being compiled under mulitiple versions of the Swift compiler. This sometimes requires conditionally compiling portions of the code depending on the version of Swift with the swift directive. This can become quite messy when a library stretches multiple major versions of the compiler and minor versions of Swift (like 4.1) introduce changes which are applied whatever the compatibility version (as is often the case with Standard Library changes). It requires messy conditionals:
#if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
array.compactMap({ $0 })
#else
array.flatMap({ $0 })
#endif
If we accept and merge this proposal, we can simplify those conditionals for future versions of Swift:
#if compiler(>=4.2)
// Use feature introduced in 4.2
#else
// Use backwards compatible implementation
#endif
Of course, for applications or libraries which always require the latest version of the compiler, the swift and compiler directive would be semantically equivalent.
Confusion 2: If this proposal is accepted, would the swift directive still be useful?
It seems the answer to this question is yes only if certain features introduced in newer versions of the compiler are not backported in compatibility mode:
#if swift(>=4.2)
// Use feature only enabled in Swift 4.2 (no compatibility mode)
#endif
Table
Here's a table to recap and help me think:
F1: Feature introduced in 4.2 and available in compatibility mode
F2: Fetaure introduced in 4.2 and not available in compatibility mode
F3: Feature introduced in 5.1 and available in compatibility mode
F4: Fetaure introduced in 5.1 and not available in compatibility mode
| Compiler Invocations |
swift directive version |
compiler directive version |
F1 |
F2 |
F3 |
F4 |
| Swift 3.1 |
3.1 |
N/A |
|
|
|
|
| Swift 4.0 |
4.0 |
N/A |
|
|
|
|
| Swift 4.0 (--swift-version 3) |
3.2 |
N/A |
|
|
|
|
| Swift 4.1 |
4.1 |
N/A |
|
|
|
|
| Swift 4.1 (--swift-version 3) |
3.3 |
N/A |
|
|
|
|
| Swift 4.2 |
4.2 |
4.2 |
X |
X |
|
|
| Swift 4.2 (--swift-version 3) |
3.4 |
4.2 |
X |
|
|
|
| Swift 4.2 (--swift-version 4) |
4.1.50 |
4.2 |
X |
|
|
|
| Swift 4.2 (--swift-version 4.2) |
4.2 |
4.2 |
X |
|
|
|
| Swift 5.0 |
5.0 |
5.0 |
X |
X |
|
|
| Swift 5.0 (--swift-version 3) |
3.5? |
5.0 |
X |
|
|
|
| Swift 5.0 (--swift-version 4) |
4.3? |
5.0 |
X |
X |
|
|
| Swift 5.0 (--swift-version 4.2) |
? |
5.0 |
X |
X |
|
|
| Swift 5.1 |
5.1 |
5.1 |
X |
X |
X |
X |
| Swift 5.1 (--swift-version 3) |
3.6? |
5.1 |
X |
X |
X |
|
| Swift 5.1 (--swift-version 4) |
4.4? |
5.1 |
X |
X |
X |
|
| Swift 5.1 (--swift-version 4.2) |
? |
5.1 |
X |
X |
X |
|
| Swift 5.2 |
5.2 |
5.2 |
X |
X |
X |
X |
| Swift 5.2 (--swift-version 3) |
3.7? |
5.2 |
X |
X |
X |
|
| Swift 5.2 (--swift-version 4) |
4.5? |
5.2 |
X |
X |
X |
|
| Swift 5.2 (--swift-version 4.2) |
? |
5.2 |
X |
X |
X |
|
Using feature F1 with swift directive alone
#if swift(>=4.2) || (swift(>=3.4) && !swift(>=4.0))
// use F1
#endif
Using feature F1 with compiler directive alone
#if compiler(>=4.2)
// use F1
#endif
Using feature F2 with swift directive alone
#if swift(>=4.2)
// use F2
#endif
Using feature F2 with compiler directive alone
Impossible.
Using feature F3 with swift directive alone
This is a clear example of why its not tenable with swift alone:
#if swift(>=5.1) || (swift(>=4.4) && !swift(>=5.0)) || (swift(>=3.6) && !swift(>=4.0))
// use F1
#endif
Using feature F3 with compiler directive alone
#if compiler(>=5.1)
// use F1
#endif
Using feature F4 with swift directive alone
#if swift(>=5.1)
// use F2
#endif
Using feature F4 with compiler directive alone
Impossible.