I don't care about the $ being concise, and it wasn't chosen for aesthetics. The $ syntax was chosen because existing Swift compilers already support it: $ can be at the start of a normal identifier (since at least Swift 3, probably earlier), but as with other $ identifiers in the language (for property wrappers, implicit closure arguments) you cannot define an entity with a $ name yourself. So the $ handy for compatibility with older tools... which is the point of the feature. (Note: @beccadax came up with the idea of using $ back when we introduced async/await into the compiler, I'm just codifying it now).
That doesn't mean we can't have the hasFeature(AsyncAwait) syntax, but it has downsides. If I were to write:
#if hasFeature(AsyncAwait)
// ..
#endif
I'll get an error like this on all compilers that predate the hasFeature syntax:
error: unexpected platform condition (expected 'os', 'arch', or 'swift')
Now, one can work around it with nesting:
#if compiler(>=5.7)
#if hasFeature(AsyncAwait)
// ..
#endif
#endif
... but if you have an #else block, you need to duplicate it: once for the inner if, once for the outer if.
Clang got around the issue when it introduced __has_feature(X) because you could use macro tricks to deal with older compilers, e.g.,
// C, not Swift!
#ifndef __has_feature
# define __has_feature(X) 0
#endif
We don't have that option in Swift.
So, while I'm usually on the side of "pick the best syntax and we'll evolve toward it," a feature like this that's 100% about backward-compatibility benefits from working with existing and older compilers.
I'm happy with one of these... perhaps -enable-future-feature and -enable-experimental-feature.
I intentionally proposed strings so that we don't need to revise the SwiftPM manifest format for each new feature we add. For example, let's say that Swift 5.9 adds conciseMagicFile. If you adopt that feature in the manifest like this:
.target(name: "MyPackage",
languageFeatures: [ .conciseMagicFile ])
Then your manifest will only compile properly on Swift 5.9; SwiftPM in Swift 5.8 won't know about the conciseMagicFile case. Now, you can deal with this with versioned manifest files, but it requires duplicating the manifest for each Swift version in which a feature was used that you want to enable. Personally, I think the cost of having to look up a string "ConciseMagicFile" once in a while is lower than the ongoing burden of maintaining multiple manifest files, hence the stringly-typed features.
I think it would be great for swift.org to contain a list of features w/ their associated versions and, if we go forward with this proposal, the feature-enablement name.
Yes, backward-compatibility is important here. Package authors especially would like to opt-in to new features when they are available, without breaking compatibility with older tools versions. With the proposal as written, they can add the appropriate feature to their package manifest and then use #if $FeatureName to conditionally use the feature. This was quite important with the introduction of concurrency, for example, and a number of libraries made use of the semi-documented #if compiler(>=5.5) && $AsyncAwait to add async interfaces when built with new-enough tools.
I agree with this in the narrow case where one has specified both a feature-enablement flag (-enable-future-feature ConciseMagicFile) and a Swift language version that enables that feature by default (-swift-version 6). Did you mean for the warning/log to occur in other cases than that?
A flag like this would necessarily change meaning from one Swift release to the next as we add new "Swift 6" features, breaking source at each step, so I'm concerned about adding it. Perhaps there could be a different flag whose role is to warn about any features that the compiler knows about that haven't been explicitly specified. That way, you would get warnings if you haven't opted into a feature that's available, but the list of features that's enabled is still what was specified by the developer.
No, I should probably have both futureLanguageFeatures: and experimentalLanguageFeatures:.
We could put them into the "experimental" category, rather than inventing something new.
I don't think the SE numbers have a lot of meaning to folks outside this forum. Identifiers like AsyncAwait and ConciseMagicFile are far more immediately recognizable when you read them in, e.g., a package manifest or in source code.
Doug