Skip to content

Instantly share code, notes, and snippets.

@ole
Last active November 8, 2024 05:53
Show Gist options
  • Save ole/478874632fca61869928a0cc0a956972 to your computer and use it in GitHub Desktop.
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.
#!/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
#!/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
@ole
Copy link
Author

ole commented Feb 16, 2024

(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)

@ole
Copy link
Author

ole commented May 12, 2024

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