# \[Pitch\] Language Mode Compiler Condition

**URL:** <https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963>\
**Category:** Pitches\
**Created:** [August 14, 2024, 11:00pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963 "2024-08-14T23:00:24Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![James\_Dempsey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/james_dempsey/32/14336_2.png) [@James\_Dempsey](https://forums.swift.org/u/James_Dempsey)\
**Post date:** [August 14, 2024, 11:00pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/1 "2024-08-14T23:00:24Z")

</div>

This is a follow-on proposal to SE-0441. It was originally included as part of the original pitch for but split into its own proposal.

Your feedback and comments are greatly appreciated.

UPDATE: To allow for a pending revision of the proposal I have moved the text of the proposal to a gist.

(As of Aug 30, 2024 I have not yet had an opportunity to update the proposal and at a certain point, forum posts become uneditable.)

> <https://gist.github.com/dempseyatgithub/9c4d2818c505399b124fd91870e929f2>

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [August 14, 2024, 11:18pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/2 "2024-08-14T23:18:41Z")

</div>

I need to think more, but one immediate reaction is that the warning text should include your "This code will always / never compile." statement so it's clear to the user what's happening with it.

---

<div class="post-metadata">

**Author:** ![j-f1](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/j-f1/32/12287_2.png) [@j-f1](https://forums.swift.org/u/j-f1)\
**Post date:** [August 15, 2024, 12:28am UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/3 "2024-08-15T00:28:24Z")

</div>

And, in my opinion, the warning for `languageMode(>=oldVersion)` should offer a Fix-It that removes the `#if` and `#endif` lines, at least in simple cases.

---

<div class="post-metadata">

**Author:** ![Finagolfin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/finagolfin/32/34388_2.png) [@Finagolfin](https://forums.swift.org/u/Finagolfin)\
**Post date:** [August 15, 2024, 5:18am UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/4 "2024-08-15T05:18:36Z")

</div>

It would help the pitch to list [the currently accepted language modes](https://github.com/swiftlang/swift/blob/1d961ba22dd0284d99eab28418395bfe2ecc8e14/lib/Basic/Version.cpp#L171): 4, 4.2, 5, and 6. Obviously some of those will also be dropped in the future, while 7 and so on will be added.

> [@James\_Dempsey](#):
>
> The existing `swift()` compilation condition checks specific versions of Swift but does so taking the current language mode into account.
> 
> This hybrid behavior can be difficult to explain and reason about

> [@James\_Dempsey](#):
>
> No changes are proposed for the existing `swift()` compilation condition. It will remain as-is.

Maybe `swift()` should be modified, deprecated, warned, or further documented in some way, since it is so problematic.

---

<div class="post-metadata">

**Author:** ![benrimmington](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benrimmington/32/695_2.png) [@benrimmington](https://forums.swift.org/u/benrimmington)\
**Post date:** [August 15, 2024, 7:14am UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/5 "2024-08-15T07:14:58Z")

</div>

> [@James\_Dempsey](#):
>
> This hybrid behavior can be difficult to explain and reason about …

You could link to the [SE-0212](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0212-compiler-version-directive.md) proposal.

* * *

> [@James\_Dempsey](#):
>
> The new compiler condition will only accept the defined set of language mode values. The compiler will generate an error if provided a value that is not a valid language mode. This mirrors the behavior of the existing compiler command-line option.

An unknown `-language-mode` argument must be an error, but an unknown `languageMode()` argument could be a warning. For example:

```swift
#if arch(x86)
// ^~~
// warning: unknown architecture for build configuration 'arch'
// note: did you mean 'i386'?
#endif

```

On the other hand, the following compiles without warning (in Xcode 16 beta 5).

```swift
#if compiler(>=7) && languageMode(>=7)
#endif

```

* * *

> [@James\_Dempsey](#):
>
> compilaiton  
> compatibiity

Typos.

---

<div class="post-metadata">

**Author:** ![filiplazov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filiplazov/32/7886_2.png) [@filiplazov](https://forums.swift.org/u/filiplazov)\
**Post date:** [August 15, 2024, 7:20am UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/6 "2024-08-15T07:20:20Z")

</div>

+1  
I wanted to migrate some parts of my code to the new language mode but they don't compile with Xcode 15.4 (only with beta). This can make the transition a bit easier.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [August 15, 2024, 3:45pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/7 "2024-08-15T15:45:20Z")

</div>

> [@j-f1](#):
>
> And, in my opinion, the warning for `languageMode(>=oldVersion)` should offer a Fix-It that removes the `#if` and `#endif` lines, at least in simple cases.

I don’t think so: if the same code is meant to compile with an older compiler, this fix-it would actively encourage breaking the code. There needs to be a way to silence the warning in source without removing the conditional for older compiler versions.

---

<div class="post-metadata">

**Author:** ![James\_Dempsey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/james_dempsey/32/14336_2.png) [@James\_Dempsey](https://forums.swift.org/u/James_Dempsey)\
**Post date:** [August 15, 2024, 10:51pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/8 "2024-08-15T22:51:42Z")

</div>

> [@Finagolfin](#):
>
> It would help the pitch to list [the currently accepted language modes](https://github.com/swiftlang/swift/blob/1d961ba22dd0284d99eab28418395bfe2ecc8e14/lib/Basic/Version.cpp#L171): 4, 4.2, 5, and 6. Obviously some of those will also be dropped in the future, while 7 and so on will be added.

Thanks, that would definitely help flesh out the proposal.

> [@Finagolfin](#):
>
> Maybe `swift()` should be modified, deprecated, warned, or further documented in some way, since it is so problematic.

The behavior of `swift()` needs to stay the same to avoid breaking existing code that depends on it.

Even though it is not straightforward to use as a language mode condition, the behavior of `swift()` is not incorrect.

The behavior of `swift()` is not incorrect, but it is not always straightforward to use as a language mode condition. I don’t think it rises to the level of causing active harm and needs to be deprecated or removed.

---

<div class="post-metadata">

**Author:** ![James\_Dempsey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/james_dempsey/32/14336_2.png) [@James\_Dempsey](https://forums.swift.org/u/James_Dempsey)\
**Post date:** [August 15, 2024, 11:20pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/9 "2024-08-15T23:20:16Z")

</div>

> [@benrimmington](#):
>
> > [@James\_Dempsey](#):
> >
> > This hybrid behavior can be difficult to explain and reason about …
> 
> You could link to the [SE-0212](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0212-compiler-version-directive.md) proposal.

Yes, I will add a link to that proposal, although even that proposal doesn't seem to cover the full range of behavior of `swift()`.

> [@benrimmington](#):
>
> An unknown `-language-mode` argument must be an error, but an unknown `languageMode()` argument could be a warning. For example:
> 
> ```swift
> #if arch(x86)
> // ^~~
> // warning: unknown architecture for build configuration 'arch'
> // note: did you mean 'i386'?
> #endif
> 
> ```

Yes, it also occurred to me that sometimes packages need to be compiled with multiple versions of the compiler, so specifying `languageMode(<7)` in a hypothetical Swift 7.0 compiler would generate an error in a Swift 6.x compiler.

I think it is desirable for the compiler to be strict within the range of language modes that it knows about. In the Swift 6.0 compiler that would be 4, 4.2, 5, 6.

So, any semantic version value between 4 and 6 that aren't a valid language mode should be an error.

All past language modes that are no longer supported are also known, so even there semantic versions less than 4 can be checked to ensure they are valid language modes.

For semantic versions beyond the highest language mode, the compiler could possible emit a warning, or possible accept it as is.

I would prefer to emit a warning, but that then runs afoul of people who prefer 'treat warnings as errors'.

Of course, since this functionality would likely be available in Swift 6.1 or later, this would not be an issue until a language mode beyond Swift 6 is introduced (which hopefully is a long while) and possibly the facility to suppress individual warnings will be added to the language by then.

---

<div class="post-metadata">

**Author:** ![fclout](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/fclout/32/36155_2.png) [@fclout](https://forums.swift.org/u/fclout)\
**Post date:** [August 16, 2024, 2:15pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/10 "2024-08-16T14:15:49Z")

</div>

As written, there are two problems which I believe need to be blocking:

- If `languageMode` only tolerates versions it knows about, then this is useless to allow new code to build with old compilers. I couldn't write `if languageMode(>=7)` to conditionally compile out code intended to build with a Swift 6 compiler because Swift 6 will reject it.
- If `languageMode` starts emitting diagnostics for versions that are not supported anymore, essentially all uses of `languageMode` are (minor) time bombs and will "stop working" (emit a diagnostic) at some point in the future. This prevents you from using languageMode to allow a code base to continue to build on old compilers.

---

<div class="post-metadata">

**Author:** ![James\_Dempsey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/james_dempsey/32/14336_2.png) [@James\_Dempsey](https://forums.swift.org/u/James_Dempsey)\
**Post date:** [August 16, 2024, 3:58pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/11 "2024-08-16T15:58:11Z")

</div>

Thank you for your feedback.

> [@fclout](#):
>
> If `languageMode` only tolerates versions it knows about, then this is useless to allow new code to build with old compilers. I couldn't write `if languageMode(>=7)` to conditionally compile out code intended to build with a Swift 6 compiler because Swift 6 will reject it.

Yes, this is definitely something I missed in the original pitch I posted. I have noted this in [a post](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/9) earlier in the thread. I have not had a chance yet to flesh out the details and incorporate this into the pitch itself, but I intend to do so.

> [@fclout](#):
>
> If `languageMode` starts emitting diagnostics for versions that are not supported anymore, essentially all uses of `languageMode` are (minor) time bombs and will "stop working" (emit a diagnostic) at some point in the future. This prevents you from using languageMode to allow a code base to continue to build on old compilers.

I don't believe that emitting a warning is equivalent to making something "stop working".

The behavior for previously supported language modes follows the same pattern as symbol deprecations. If you build using a prior compiler release there is no warning, if you build the same code on the release where a deprecation occurs, or in this case where a referenced language mode is no longer supported, there is a warning.

Also note that `languageMode()` can be used in conjunction with the `compiler()` compilation condition to accommodate different code paths depending on the compiler version and language mode.

---

<div class="post-metadata">

**Author:** ![benrimmington](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benrimmington/32/695_2.png) [@benrimmington](https://forums.swift.org/u/benrimmington)\
**Post date:** [August 17, 2024, 3:17am UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/12 "2024-08-17T03:17:49Z")

</div>

The `@available` attribute can also use language modes. For example:

```swift
@available(swift, introduced: 4.2, deprecated: 5, obsoleted: 6)

```

will be _unavailable_ in language modes 4 and 6.

However, version numbers other than 3, 4, 4.2, 5, and 6 are currently allowed.

I'm not sure if `@available(languageMode …)` should be a future direction.

---

<div class="post-metadata">

**Author:** ![fclout](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/fclout/32/36155_2.png) [@fclout](https://forums.swift.org/u/fclout)\
**Post date:** [August 17, 2024, 3:54am UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/13 "2024-08-17T03:54:05Z")

</div>

If it's OK to indefinitely carry a warning in a code base, what is the warning protecting developers from?

---

<div class="post-metadata">

**Author:** ![James\_Dempsey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/james_dempsey/32/14336_2.png) [@James\_Dempsey](https://forums.swift.org/u/James_Dempsey)\
**Post date:** [August 17, 2024, 3:48pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/14 "2024-08-17T15:48:13Z")

</div>

> [@fclout](#):
>
> If it's OK to indefinitely carry a warning in a code base, what is the warning protecting developers from?

In this case, it is warning a developer that the language mode referenced in their code is no longer supported in the current version of the compiler.

Overall though, different developers and organizations handle warnings in vastly different ways. I have done work for organizations that work to address each warning as it appears and others that allow dozens of warnings in their code base for long periods of time.

The proposed behavior for previously supported language modes follows the same pattern of warning as deprecated symbols. But the overall philosophy of warnings in general and how developers should handle them is beyond the scope of the proposal.

---

<div class="post-metadata">

**Author:** ![fclout](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/fclout/32/36155_2.png) [@fclout](https://forums.swift.org/u/fclout)\
**Post date:** [August 17, 2024, 5:26pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/15 "2024-08-17T17:26:58Z")

</div>

It cannot be beyond the scope of this proposal to decide when warnings are appropriate if this proposal includes a warning. It would not be responsible language design to accept all diagnostics until there are core guidelines on when it is appropriate to have a diagnostic.

The danger advertised by a deprecation warning is that the API will go away entirely in a future release and/or bugs reported against it won't be fixed anymore. That danger makes it worth a diagnostic. We can do this exercise for all existing diagnostics. I think that we need to do it here.

When people run into false positive diagnostics, they file bugs against the compiler. For instance, it used to be that using `var (foo, bar) = blah()` and modifying only one of `foo` or `bar` would diagnose that it should be a `let` binding, which is incorrect.

Given a warning that can have false positives (code can be built with old and new compilers alike), I feel that its existence must have a stronger basis than there being another similar diagnostic that exists for its own enunciable reasons (which are inapplicable to the new one).

---

<div class="post-metadata">

**Author:** ![James\_Dempsey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/james_dempsey/32/14336_2.png) [@James\_Dempsey](https://forums.swift.org/u/James_Dempsey)\
**Post date:** [August 17, 2024, 5:59pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/16 "2024-08-17T17:59:46Z")

</div>

> [@fclout](#):
>
> We can do this exercise for all existing diagnostics. I think that we need to do it here.

Yes, that is being done here. The warning exists to let the developer know that the language mode referenced in the compilation condition is no longer supported by the version of the compiler that emits the warning.

Your earlier post made the case that emitting a warning would make the code "stop working" when the developer moved to the new compiler, if the code needed to compile on the current and previous versions of the compiler.

I made the analogy to deprecation warnings because those do not prevent a developer from having their code compile on current and previous compiler versions. The same techniques developers use for these warnings can be used for the proposed warning.

> [@fclout](#):
>
> Given a warning that can have false positives...

I am not sure what you mean that this warning would generate false positives. If the compilation condition uses a language mode the compiler supports, no warning is emitted. If the compilation condition uses a previously supported language mode, a warning is emitted.

---

<div class="post-metadata">

**Author:** ![j-f1](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/j-f1/32/12287_2.png) [@j-f1](https://forums.swift.org/u/j-f1)\
**Post date:** [August 17, 2024, 6:12pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/17 "2024-08-17T18:12:22Z")

</div>

Why not assume that any language mode with a numeric value less than the lowest currently supported language mode is a valid language mode that the current language mode is greater than, and any language mode with a value higher than the current compiler version is greater than any supported language mode? That way there would never be a diagnostic produced for future or no-longer-supported language modes, but users would still receive assistance when using an invalid language mode like `5.7`.

A parallel but separate feature could be to add a compiler option to produce diagnostics for old language modes and `#available`/`@available` declarations with values lower than the deployment target, which would enable developers to actively choose to identify and clean up these sorts of dead conditionals, rather than being forced to look at false warnings all the time.

---

<div class="post-metadata">

**Author:** ![James\_Dempsey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/james_dempsey/32/14336_2.png) [@James\_Dempsey](https://forums.swift.org/u/James_Dempsey)\
**Post date:** [August 17, 2024, 6:23pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/18 "2024-08-17T18:23:02Z")

</div>

> [@benrimmington](#):
>
> The `@available` attribute can also use language modes. For example:
> 
> ```swift
> @available(swift, introduced: 4.2, deprecated: 5, obsoleted: 6)
> 
> ```
> 
> will be _unavailable_ in language modes 4 and 6.
> 
> However, version numbers other than 3, 4, 4.2, 5, and 6 are currently allowed.

Yes, I think it might be most accurate to say that

```swift
@available(swift, ...)

```

takes the current language mode into account when determining availability.

The swift availability attribute is at the granularity of specific Swift / compiler / toolchain versions since things can potentially be introduced, deprecated, etc. in any release.

I believe the current behavior of taking the current language mode into account when determining availability is the correct behavior and does not need to change.

I also think that determining availability is a different topic beyond what is proposed. The compilation condition is intended as a straightforward condition for "I want this code to run in Language Mode 6 and later and this code to run in every language mode before 6." (and of course, the various 'elseifs' possible.)

> [@benrimmington](#):
>
> I'm not sure if `@available(languageMode …)` should be a future direction.

I don't think availability based on language mode should be a future direction. It is most natural to express availability based on the specific version that the availability of a symbol changes. Since determining availability already takes the language mode being used to compile into account, using the existing availability attribute as designed already gives the desired results.

---

<div class="post-metadata">

**Author:** ![James\_Dempsey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/james_dempsey/32/14336_2.png) [@James\_Dempsey](https://forums.swift.org/u/James_Dempsey)\
**Post date:** [August 17, 2024, 6:33pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/19 "2024-08-17T18:33:00Z")

</div>

> [@j-f1](#):
>
> Why not assume that any language mode with a numeric value less than the lowest currently supported language mode is a valid language mode that the current language mode is greater than, and any language mode with a value higher than the current compiler version is greater than any supported language mode? That way there would never be a diagnostic produced for future or no-longer-supported language modes, but users would still receive assistance when using an invalid language mode like `5.7`.

I think there are two different cases of unsupported language modes.

For now-unsupported language modes, I believe there should be a warning because, generally, when moving to a new version of the compiler and your code contains things that are no longer supported, deprecated, etc. a warning is generated to warn the developer of those issues. (i.e. the support or availability of something in your existing code has changed in this release of the compiler and you are being warned/alerted to that change.)

For future unsupported versions, as discussed in an earlier post, as I think more about it, I'm coming around to thinking those should not emit a warning. I haven't written out the full rationale yet but will update the pitch once I have a chance.

> [@j-f1](#):
>
> A parallel but separate feature could be to add a compiler option to produce diagnostics for old language modes and `#available`/`@available` declarations with values lower than the deployment target, which would enable developers to actively choose to identify and clean up these sorts of dead conditionals, rather than being forced to look at false warnings all the time.

Yes, I think that would be a separate feature beyond the scope of the proposal.

---

<div class="post-metadata">

**Author:** ![j-f1](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/j-f1/32/12287_2.png) [@j-f1](https://forums.swift.org/u/j-f1)\
**Post date:** [August 17, 2024, 7:20pm UTC](https://forums.swift.org/t/pitch-language-mode-compiler-condition/73963/20 "2024-08-17T19:20:10Z")

</div>

> [@James\_Dempsey](#):
>
> For now-unsupported language modes, I believe there should be a warning because, generally, when moving to a new version of the compiler and your code contains things that are no longer supported, deprecated, etc. a warning is generated to warn the developer of those issues.

I don’t think API deprecations are really a good comparison for language mode checks. API deprecation warnings only appear (at least for OS libraries) when you update your deployment target to match or exceed the version where the deprecation happened. I don’t think there is really a mechanism to do that kind of staged deprecation for SwiftPM dependencies (probably because you control the version of the dependency you use?). However, language mode checks are much like compiler version checks in that they allow you to work around differences between different versions of the language’s syntax and semantics. That’s why I think the compiler should either commit to never removing a supported language mode, or commit to never warning about a language mode check that a released version of the compiler accepts without a warning: the whole point of this feature is to allow code to be written that can be compiled with a wide variety of compiler versions without causing diagnostics to be emitted.
