Last active
November 21, 2024 10:32
-
-
Save ole/478874632fca61869928a0cc0a956972 to your computer and use it in GitHub Desktop.
swift-list-feature: List Swift compiler upcoming and experimental feature flags. ★ swift-has-feature: Check if a given compiler knows a specific feature flag, and whether it's an upcoming or experimental flag.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/zsh | |
# Test if the Swift compiler knows about a particular language feature. | |
# | |
# Usage: | |
# | |
# swift-has-feature [--swift SWIFT_PATH] [--language-version LANGUAGE_VERSION] FEATURE | |
# | |
# The feature should be an upcoming or experimental language feature, | |
# such as `"StrictConcurrency"` or `"ExistentialAny"`. | |
# | |
# Use swift-list-features.sh to list all known features of a given compiler version. | |
read -r -d '' usage << EOF | |
$(tput bold)USAGE:$(tput sgr0) swift-has-feature [--swift <path_to_swift>] [--language-version <language_version>] <feature> | |
Test if the Swift compiler knows about a particular language feature. | |
$(tput bold)OPTIONS$(tput sgr0) | |
feature A named Swift language feature, such as "StrictConcurrency". | |
Use swift-list-features.sh to list all known features. | |
--swift <path_to_swift> Path to the Swift compiler you want to test. | |
Default: "swift". | |
--language-version <version> Set the language version you want to test. | |
We pass this to the compiler with the -swift-version flag. | |
Default: whatever the Swift compiler uses by default. | |
$(tput bold)EXAMPLES$(tput sgr0) | |
swift-has-feature ExistentialAny | |
swift-has-feature --language-version 6 StrictConcurrency | |
swift-has-feature --swift /Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swift --language-version 6 StrictConcurrency | |
EOF | |
zmodload zsh/zutil | |
zparseopts -D -F -- -swift:=arg_swift_path -language-version:=arg_language_version || exit 1 | |
if test -z "$1"; then | |
echo "$usage" | |
exit | |
fi | |
if test -z "${arg_swift_path[*]}"; then | |
swift_path=("swift") | |
else | |
# $arg_swift_path is an array of the form ("--swift" "/path/to/swift -arguments") | |
# Take the last argument. | |
swift_path=${arg_swift_path[-1]} | |
fi | |
swift_args=() | |
if test -n "${arg_language_version[*]}"; then | |
# $arg_language_version is an array of the form ("--language_version" "6"). | |
# Take the last argument. | |
language_version=${arg_language_version[-1]} | |
swift_args+=("-swift-version" "$language_version") | |
fi | |
# Print compiler and language version. | |
echo -n "$(tput bold)Swift compiler version:$(tput sgr0) " | |
"$swift_path" --version | |
if test -z "${arg_swift_path[*]}"; then | |
echo "(Pass --swift <path_to_swift> to test a different compiler executable.)" | |
fi | |
echo "" | |
echo "$(tput bold)Language version:$(tput sgr0) ${language_version:-"(default)"}" | |
if test -z "$language_version"; then | |
echo "(Pass --language-version <version> to set the language version.)" | |
fi | |
echo "" | |
# Swift code to test if a feature is known to the compiler. | |
read -r -d '' swift_script << EOF | |
import Foundation | |
#if hasFeature($1) | |
exit(EXIT_SUCCESS) | |
#else | |
exit(EXIT_FAILURE) | |
#endif | |
EOF | |
echo "$(tput setaf 3)Running Swift compiler…$(tput sgr0)" | |
# Compile and run the Swift code multiple times with different compiler flags. | |
echo "$swift_script" | "$swift_path" "${swift_args[@]}" - | |
is_builtin=$? # 0 == The feature is always on, no feature flags needed. | |
echo "$swift_script" | "$swift_path" "${swift_args[@]}" -enable-upcoming-feature "$1" - | |
is_upcoming=$? # 0 == It's an upcoming feature flag. | |
echo "$swift_script" | "$swift_path" "${swift_args[@]}" -enable-experimental-feature "$1" - | |
is_experimental=$? # 0 == It's an experimental feature flag. | |
echo "$(tput setaf 3)Done.$(tput sgr0)" | |
echo "" | |
# Print the result. | |
read -r -d '' output_upcoming << EOF | |
$(tput bold)Result:$(tput sgr0) '$1' is an $(tput bold)upcoming$(tput sgr0) feature flag. | |
Usage: | |
• swiftc $(tput bold)-enable-upcoming-feature $1$(tput sgr0) | |
• SwiftPM $(tput bold).enableUpcomingFeature($1)$(tput sgr0) | |
EOF | |
read -r -d '' output_experimental << EOF | |
$(tput bold)Result:$(tput sgr0) '$1' is an $(tput bold)experimental$(tput sgr0) feature flag. | |
Usage: | |
• swiftc $(tput bold)-enable-experimental-feature $1$(tput sgr0) | |
• SwiftPM $(tput bold).enableExperimentalFeature($1)$(tput sgr0) | |
EOF | |
if test $is_builtin -eq 0; then | |
echo "$(tput bold)Result:$(tput sgr0) The feature '$1' is $(tput bold)enabled unconditionally$(tput sgr0) in this language version. You can use it without passing any feature flags." | |
elif test $is_upcoming -eq 0; then | |
echo "$output_upcoming" | |
elif test $is_experimental -eq 0; then | |
echo "$output_experimental" | |
else | |
echo "$(tput bold)Result:$(tput sgr0) Unknown feature flag '$1'. The Swift compiler doesn’t know this feature." | |
exit 1 | |
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# List Swift language features the compiler knows about. | |
# | |
# Usage: | |
# | |
# swift-list-features [version] # default: main branch | |
# | |
# Examples: | |
# | |
# swift-list-features # Queries main branch | |
# swift-list-features 5.9 # Queries release/5.9 branch | |
# | |
# This script uses curl to download the file in which the language features | |
# are defined from the Swift repo and uses Clang to parse it. | |
# | |
# Original author: Gor Gyolchanyan | |
# <https://forums.swift.org/t/how-to-test-if-swiftc-supports-an-upcoming-experimental-feature/69095/10> | |
# | |
# Enhanced/modified by: Ole Begemann | |
swift_version=$1 | |
if test -z "$swift_version" || test "$swift_version" = "main"; then | |
branch="main" | |
else | |
branch="release/${swift_version}" | |
fi | |
GITHUB_URL="https://raw.githubusercontent.com/apple/swift/${branch}/include/swift/Basic/Features.def" | |
FEATURES_DEF_FILE="$(curl --fail-with-body --silent "${GITHUB_URL}")" | |
curlStatus=$? | |
if test $curlStatus -ne 0; then | |
echo "$FEATURES_DEF_FILE" | |
echo "Error: failed to download '$GITHUB_URL'. Invalid URL?" | |
exit $curlStatus | |
fi | |
echo "Swift language features in $branch" | |
echo "======================================" | |
clang --preprocess --no-line-commands -nostdinc -x c - <<EOF | sort | |
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, ...) FeatureName | |
#define UPCOMING_FEATURE(FeatureName, SENumber, Version) [Upcoming] FeatureName (Swift Version) | |
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) [Experimental] FeatureName | |
${FEATURES_DEF_FILE} | |
EOF |
Example outputs for swift-has-feature
. Note the differences between --language-version 6
and leaving the language version at its default (5) with the Swift 6.0 compiler:
Swift 5.10
$ swift-has-feature.sh StrictConcurrency
Swift compiler version: swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
(Pass --swift <path_to_swift> to test a different compiler executable.)
Language version: (default)
(Pass --language-version <version> to set the language version.)
Running Swift compiler…
Done.
Result: 'StrictConcurrency' is an experimental feature flag.
Usage:
• swiftc -enable-experimental-feature StrictConcurrency
• SwiftPM .enableExperimentalFeature(StrictConcurrency)
Swift 6.0 (language version: 5)
swift-has-feature.sh --swift /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/bin/swift StrictConcurrency
Swift compiler version: Apple Swift version 6.0-dev (LLVM 7b8e6346027d2b1, Swift 763421cee31dc8f)
Target: arm64-apple-macosx14.0
Language version: (default)
(Pass --language-version <version> to set the language version.)
Running Swift compiler…
Done.
Result: 'StrictConcurrency' is an upcoming feature flag.
Usage:
• swiftc -enable-upcoming-feature StrictConcurrency
• SwiftPM .enableUpcomingFeature(StrictConcurrency)
Swift 6.0 (language version: 6)
$ swift-has-feature.sh --swift /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/bin/swift --language-version 6 StrictConcurrency
Swift compiler version: Apple Swift version 6.0-dev (LLVM 7b8e6346027d2b1, Swift 763421cee31dc8f)
Target: arm64-apple-macosx14.0
Language version: 6
Running Swift compiler…
<unknown>:0: error: upcoming feature 'StrictConcurrency' is already enabled as of Swift version 6
Done.
Result: The feature 'StrictConcurrency' is enabled unconditionally in this language version. You can use it without passing any feature flags.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
(last updated: 2025-05-12)
Example output of
swift-list-features
for Swift 5.10:$ swift-list-features.sh 5.10 Swift language features in release/5.10 ====================================== Actors AsyncAwait AttachedMacros BuiltinAssumeAlignment BuiltinBuildComplexEqualityExecutor BuiltinBuildExecutor BuiltinBuildMainExecutor BuiltinContinuation BuiltinCopy BuiltinCreateAsyncTaskInGroup BuiltinCreateTaskGroupWithFlags BuiltinExecutor BuiltinHopToActor BuiltinIntLiteralAccessors BuiltinJob BuiltinStackAlloc BuiltinTaskGroupWithArgument BuiltinTaskRunInline BuiltinUnprotectedAddressOf BuiltinUnprotectedStackAlloc ConcurrentFunctions EffectfulProp ExtensionMacroAttr ExtensionMacros FreestandingExpressionMacros FreestandingMacros GlobalActors ImplicitSelfCapture InheritActorContext LexicalLifetimes Macros MarkerProtocol MoveOnly MoveOnlyResilientTypes NewCxxMethodSafetyHeuristics NoAsyncAvailability ParameterPacks PrimaryAssociatedTypes2 RethrowsProtocol Sendable SpecializeAttributeWithAvailability UnavailableFromAsync UnsafeInheritExecutor [Experimental] ASTGenTypes [Experimental] AccessLevelOnImport [Experimental] AdditiveArithmeticDerivedConformances [Experimental] BuiltinMacros [Experimental] BuiltinModule [Experimental] CodeItemMacros [Experimental] DifferentiableProgramming [Experimental] Embedded [Experimental] FlowSensitiveConcurrencyCaptures [Experimental] ForwardModeDifferentiation [Experimental] GenerateBindingsForThrowingFunctionsInCXX [Experimental] ImplicitSome [Experimental] ImportSymbolicCXXDecls [Experimental] LayoutPrespecialization [Experimental] LayoutStringValueWitnesses [Experimental] LayoutStringValueWitnessesInstantiation [Experimental] LazyImmediate [Experimental] ModuleInterfaceExportAs [Experimental] MoveOnlyClasses [Experimental] MoveOnlyEnumDeinits [Experimental] MoveOnlyPartialConsumption [Experimental] MoveOnlyTuples [Experimental] NamedOpaqueTypes [Experimental] NoImplicitCopy [Experimental] OldOwnershipOperatorSpellings [Experimental] OneWayClosureParameters [Experimental] OpaqueTypeErasure [Experimental] ParserASTGen [Experimental] ParserDiagnostics [Experimental] ParserRoundTrip [Experimental] ParserValidation [Experimental] PlaygroundExtendedCallbacks [Experimental] RawLayout [Experimental] ReferenceBindings [Experimental] SendNonSendable [Experimental] SendableCompletionHandlers [Experimental] StaticAssert [Experimental] StrictConcurrency [Experimental] SymbolLinkageMarkers [Experimental] ThenStatements [Experimental] TupleConformances [Experimental] TypeWitnessSystemInference [Upcoming] BareSlashRegexLiterals (Swift 6) [Upcoming] ConciseMagicFile (Swift 6) [Upcoming] DeprecateApplicationMain (Swift 6) [Upcoming] DisableOutwardActorInference (Swift 6) [Upcoming] ExistentialAny (Swift 7) [Upcoming] ForwardTrailingClosures (Swift 6) [Upcoming] GlobalConcurrency (Swift 6) [Upcoming] ImportObjcForwardDeclarations (Swift 6) [Upcoming] IsolatedDefaultValues (Swift 6)