Skip to content

Commit b9e1aae

Browse files
authored
Merge pull request #2474 from dempseyatgithub/formalize-language-mode-terminology
Proposal to formalize 'language mode' terminology
2 parents 6a0f57e + aa32c1e commit b9e1aae

File tree

1 file changed

+291
-0
lines changed

1 file changed

+291
-0
lines changed
Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
# Pitch: Formalize ‘language mode’ terminology
2+
3+
* Proposal: [SE-0441](0441-formalize-language-mode-terminology.md)
4+
* Author: [James Dempsey](https://github.com/dempseyatgithub)
5+
* Review Manager: [John McCall](https://github.com/rjmccall)
6+
* Status: **Active review (July 15th...29th, 2024)**
7+
* Implementation: [apple/swift-package-manager#7620](https://github.com/apple/swift-package-manager/pull/7620)
8+
* Review: ([first pitch](https://forums.swift.org/t/pitch-formalize-swift-language-mode-naming-in-tools-and-api/71733)), ([second pitch](https://forums.swift.org/t/pitch-2-formalize-language-mode-naming-in-tools-and-api/72136))
9+
10+
## Introduction
11+
The term "Swift version” can refer to either the toolchain/compiler version or the language mode. This ambiguity is a consistent source of confusion. This proposal formalizes the term _language mode_ in tool options and APIs.
12+
13+
## Proposed Solution
14+
The proposed solution is to use the term _language mode_ for the appropriate Swift compiler option and Swift Package Manager APIs. Use of "Swift version" to refer to language mode will be deprecated or obsoleted as needed.
15+
16+
### Terminology
17+
The term _language mode_ has been consistently used to describe this compiler feature since it was introduced with Swift 4.0 and is an established term of art in the Swift community.
18+
19+
The **Alternatives Considered** section contains a more detailed discussion of the term's history and usage.
20+
21+
### Swift compiler option
22+
Introduce a `-language-mode` option that has the same behavior as the existing `-swift-version` option, while de-emphasizing the `-swift-version` option in help and documentation.
23+
24+
#### Naming note
25+
The proposed compiler option uses the term 'language mode' instead of 'Swift language mode' because the context strongly implies a Swift language mode. The intent is that the `languageMode()` compiler condition described in **Future directions** would also use that naming convention for the same reason.
26+
27+
### Swift Package Manager
28+
Introduce four Swift Package Manager API changes limited to manifests \>= 6.0:
29+
30+
#### 1. A new Package init method that uses the language mode terminology
31+
32+
```swift
33+
@available(_PackageDescription, introduced: 6)
34+
Package(
35+
name: String,
36+
defaultLocalization: [LanguageTag]? = nil.
37+
platforms: [SupportedPlatform]? = nil,
38+
products: [Product] = [],
39+
dependencies: [Package.Dependency] = [],
40+
targets: [Target] = [],
41+
swiftLanguageModes: [SwiftLanguageMode]? = nil,
42+
cLanguageStandard: CLanguageStandard? = nil,
43+
cxxLanguageStandard: CXXLanguageStandard? = nil
44+
)
45+
```
46+
47+
Add a new `init` method to `Package` with the following changes from the current `init` method:
48+
49+
- The parameter `swiftLanguageVersions` is renamed to `swiftLanguageModes`
50+
- The parameter type is now an optional array of `SwiftLanguageMode` values instead of `SwiftVersion` values
51+
52+
The existing init method will be marked as `obsoleted` and `renamed` allowing the compiler to provide a fix-it.
53+
54+
#### 2. Rename `swiftLanguageVersions` property to `swiftLanguageModes`
55+
Rename the public `Package` property `swiftLanguageVersions` to `swiftLanguageModes`. Add a `swiftLanguageVersions` computed property that accesses `swiftLanguageModes` for backwards compatibility.
56+
57+
58+
#### 3. Rename `SwiftVersion` enum to `SwiftLanguageMode`
59+
Rename the `SwiftVersion` enum to `SwiftLanguageMode`. Add `SwiftVersion` as a type alias for backwards compatibility.
60+
61+
62+
#### 4. Add `swiftLanguageMode()` to `SwiftSetting`
63+
64+
```swift
65+
public struct SwiftSetting {
66+
// ... other settings
67+
68+
@available(_PackageDescription, introduced: 6.0)
69+
public static func swiftLanguageMode(
70+
_ mode: SwiftLanguageMode,
71+
_ condition: BuildSettingCondition? = nil
72+
)
73+
```
74+
75+
The changes in [SE-0435: Swift Language Version Per Target](https://github.com/apple/swift-evolution/blob/main/proposals/0435-swiftpm-per-target-swift-language-version-setting.md) have been implemented and released in pre-release versions of Swift 6.0. This proposal will add `swiftLanguageMode()` as a `SwiftSetting` and deprecate the `swiftLanguageVersion()` setting added by SE-0435 with a `renamed` annotation.
76+
77+
#### Naming note
78+
79+
In Swift PM manifests, multiple languages are supported. For clarity, there is existing precedent for parameter and enum type names to have a language name prefix.
80+
81+
For example the Package `init` method currently includes:
82+
83+
```swift
84+
...
85+
swiftLanguageVersions: [SwiftVersion]? = nil,
86+
cLanguageStandard: CLanguageStandard? = nil,
87+
cxxLanguageStandard: CXXLanguageStandard? = nil
88+
...
89+
```
90+
91+
For clarity and to follow the existing precedent, the proposed Swift PM APIs will be appropriately capitalized versions of "Swift language mode".
92+
93+
## Detailed design
94+
95+
### New swift compiler option
96+
A new `-language-mode` option will be added with the same behavior as the existing `-swift-version` option.
97+
98+
The `-swift-version` option will continue to work as it currently does, preserving backwards compatibility.
99+
100+
The `-language-mode` option will be presented in the compiler help.
101+
102+
The `-swift-version` option will be suppressed from the top-level help of the compiler.
103+
104+
### Swift Package Manager
105+
Proposed Swift Package Manager API changes are limited to manifests \>= 6.0:
106+
107+
### New Package init method and obsoleted init method
108+
A new `init` method will be added to `Package` that renames the `swiftLanguageVersions` parameter to `swiftLanguageModes` with the type of the parameter being an optional array of `SwiftLanguageMode` values instead of `SwiftVersion` values:
109+
110+
```swift
111+
@available(_PackageDescription, introduced: 6)
112+
Package(
113+
name: String,
114+
defaultLocalization: [LanguageTag]? = nil.
115+
platforms: [SupportedPlatform]? = nil,
116+
products: [Product] = [],
117+
dependencies: [Package.Dependency] = [],
118+
targets: [Target] = [],
119+
swiftLanguageModes: [SwiftLanguageMode]? = nil,
120+
cLanguageStandard: CLanguageStandard? = nil,
121+
cxxLanguageStandard: CXXLanguageStandard? = nil
122+
)
123+
```
124+
125+
126+
The existing init method will be marked as `obsoleted` and `renamed`, allowing the compiler to provide a fix-it:
127+
128+
```
129+
@available(_PackageDescription, introduced: 5.3, obsoleted: 6, renamed:
130+
"init(name:defaultLocalization:platforms:pkgConfig:providers:products:
131+
dependencies:targets:swiftLanguageModes:cLanguageStandard:
132+
cxxLanguageStandard:)")
133+
public init(
134+
name: String,
135+
...
136+
swiftLanguageVersions: [SwiftVersion]? = nil,
137+
cLanguageStandard: CLanguageStandard? = nil,
138+
cxxLanguageStandard: CXXLanguageStandard? = nil
139+
) {
140+
```
141+
142+
#### Obsoleting existing init method
143+
The existing method must be obsoleted because the two methods are ambiguous when the default value for `swiftLanguageVersions` / `swiftLanguageModes` is used:
144+
145+
```
146+
Package ( // Error: Ambiguous use of 'init'
147+
name: "MyPackage",
148+
products: ...,
149+
targets: ...
150+
)
151+
```
152+
153+
This follows the same approach used by all past revisions of the Package `init` method.
154+
155+
See the **Source compatibiity** section for more details about this change.
156+
157+
### Rename `swiftLanguageVersions` property to `swiftLanguageModes`
158+
Rename the `Package` public property `swiftLanguageVersions` to `swiftLanguageModes`. Introduce a computed property named `swiftLanguageModes` that accesses the renamed stored property for backwards compatibility.
159+
160+
The computed property will be annotated as `deprecated` in Swift 6 and `renamed` to `swiftLanguageModes`.
161+
162+
For packages with swift tools version less than 6.0, accessing the `swiftLanguageModes` property will continue to work.
163+
164+
For 6.0 and later, that access will be a warning with a fix-it to use the new property name.
165+
166+
```swift
167+
@available(_PackageDescription, deprecated: 6.0, renamed: "swiftLanguageModes")
168+
public var swiftLanguageVersions: [SwiftVersion]? {
169+
get { swiftLanguageModes }
170+
set { swiftLanguageModes = newValue }
171+
}
172+
```
173+
174+
See the **Source compatibility** section for more details about this change.
175+
176+
### Rename `SwiftVersion` enum to `SwiftLanguageMode`
177+
Rename the existing `SwiftVersion` enum to `SwiftLanguageMode` with `SwiftVersion` added back as a type alias for backwards compatibility. The type alias will be deprecated in 6.0 with a `renamed` annotation to `SwiftLanguageMode`.
178+
179+
This change will not affect serialization of PackageDescription types. Serialization is handled by converting PackageDescription types into separate, corresponding Codable types. The existing serialization types will remain as-is.
180+
181+
182+
### Add `swiftLanguageMode()` to `SwiftSetting`
183+
Add a new `swiftLanguageMode()` static function to `SwiftSetting` with the same behavior of `swiftLanguageBehavior()` added by [SE-0435](https://github.com/apple/swift-evolution/blob/main/proposals/0435-swiftpm-per-target-swift-language-version-setting.md):
184+
185+
```swift
186+
public struct SwiftSetting {
187+
// ... other settings
188+
189+
@available(_PackageDescription, introduced: 6.0)
190+
public static func swiftLanguageMode(
191+
_ mode: SwiftLanguageMode,
192+
_ condition: BuildSettingCondition? = nil
193+
)
194+
```
195+
196+
The name of the function is `swiftLanguageMode()` instead of `languageMode()` to keep naming consistent with the `swiftLanguageModes` parameter of the Package init method. The parameter label `mode` is used to follow the precedent set by the existing `interoperabilityMode()` method in `SwiftSetting`.
197+
198+
Deprecate the `swiftLanguageVersion()` setting added by SE-0435 with a `renamed` annotation to provide a fix-it for developers who have adopted this API in pre-release versions of Swift 6.0.:
199+
200+
```swift
201+
public struct SwiftSetting {
202+
// ... other settings
203+
204+
@available(_PackageDescription, introduced: 6.0, deprecated: 6.0, renamed: "swiftLanguageMode(_:_:)")
205+
public static func swiftLanguageVersion(
206+
_ version: SwiftVersion,
207+
_ condition: BuildSettingCondition? = nil
208+
) -> SwiftSetting {
209+
...
210+
}
211+
}
212+
```
213+
214+
## Source compatibility
215+
The new Package `init` method and obsoleting of the existing `init` method will cause source breakage for package manifests that specify the existing `swiftLanguageVersions` parameter when updating to swift tools version 6.0
216+
217+
A search of manifest files in public repositories suggests that about 10% of manifest files will encounter this breakage.
218+
219+
Because the obsoleted `init` method is annotated as `renamed` the compiler will automatically provide a fix-it to update to the new `init` method.
220+
221+
Renaming the public `swiftLanguageVersions` property of `Package` preserves backwards compatibility by introducing a computed property with that name. The computed property will be marked as `deprecated` in 6.0 and annotated as `renamed` to provide a fix-it.
222+
223+
Searching manifest files in public repositories suggests that accessing the `swiftLanguageVersions` property directly is not common.
224+
225+
The `SwiftVersion` type alias will be deprecated in favor of the `SwiftLanguageMode` enum. This also will provide a fix-it.
226+
227+
Finally the `swiftLanguageVersion()` method in `SwiftSetting` added as part of SE-0435 will be deprecated in favor of the `swiftLanguageMode()` method with a fix-it.
228+
229+
## ABI compatibility
230+
This proposal has no effect on ABI stability.
231+
232+
## Future directions
233+
This proposal originally included the proposed addition of a `languageMode()` compilation condition to further standardize on the terminology and allow the compiler to check for valid language mode values.
234+
235+
That functionality has been removed from this proposal with the intent to pitch it separately. Doing so keeps this proposal focused on the tools, including the source breaking API changes. The future direction is purely additive and would focus on the language change.
236+
237+
## Alternatives considered
238+
239+
### Alternate terminology
240+
241+
In the pitch phase, a number of terms were suggested as alternatives for _language mode_. Some concerns were also expressed that the term _language mode_ may be too broad and cause future ambiguity.
242+
243+
The intent of this proposal is to formalize established terminology in tool options and APIs.
244+
245+
The term _language mode_ is a long-established term of art in the Swift community to describe this functionality in the compiler.
246+
247+
This includes the [blog post](https://www.swift.org/blog/swift-4.0-released/) announcing the functionality as part of the release of Swift 4 in 2017 (emphasis added):
248+
249+
> With Swift 4, you may not need to modify your code to use the new version of the compiler. The compiler supports two _language modes_…
250+
251+
> The _language mode_ is specified to the compiler by the -swift-version flag, which is automatically handled by the Swift Package Manager and Xcode.
252+
>
253+
> One advantage of these _language modes_ is that you can start using the new Swift 4 compiler and migrate fully to Swift 4 at your own pace, taking advantage of new Swift 4 features, one module at a time.
254+
255+
Usage also includes posts in the last year from LSG members about Swift 6 language mode:
256+
257+
- [Design Priorities for the Swift 6 Language Mode](https://forums.swift.org/t/design-priorities-for-the-swift-6-language-mode/62408/27)
258+
- [Progress toward the Swift 6 language mode](https://forums.swift.org/t/progress-toward-the-swift-6-language-mode/68315)
259+
260+
Finally, searching for "language modes" and "language mode" in the Swift forums found that at least 90% of the posts use the term in this way. Many of the remaining posts use the term in the context of Clang.
261+
262+
#### Alternatives mentioned
263+
264+
Alternate terms raised as possibilities were:
265+
- _Edition_: a term used by Rust for a similar concept
266+
- _Standard_: similar to C or C++ standards
267+
Language standards tend to be associated with a written specification, which Swift does not currently have.
268+
Using the term _standard_ would preclude using the term in the future to describe a formal standard.
269+
270+
271+
#### Potential overload of _language mode_
272+
Some reviewers raised concern that Embedded Swift could be considered a language mode and lead to future ambiguity.
273+
274+
On consideration, this concern is mitigated in two ways:
275+
276+
1. As noted above, the term _language mode_ is a well-established term of art in the Swift community.
277+
278+
2. The term _Embedded Swift_ already provides an unambiguous, concise name that can be discussed without requiring a reference to modes.
279+
280+
This is demonstrated by the following hypothetical FAQ based on the Embedded Swift vision document:
281+
> _What is Embedded Swift?_
282+
> Embedded Swift is a subset of Swift suitable for restricted environments such as embedded and low-level environments.
283+
>
284+
> _How do you enable Embedded Swift?_
285+
> Pass the `-embedded` compiler flag to compile Embedded Swift.
286+
287+
Considering these alternatives, it seems likely that introducing a new term to replace the long-established term _language mode_ and potentially giving the existing term a new meaning would lead to more ambiguity than keeping and formalizing the existing meaning of _language mode_.
288+
289+
## Acknowledgments
290+
291+
Thank you to Pavel Yaskevich for providing guidance and assistance in the implementation of this proposal.

0 commit comments

Comments
 (0)