From ccc5a71028e763d06510f0ea10c226ce2edad2ca Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Tue, 30 Apr 2024 06:41:24 -0700 Subject: [PATCH] Add the `swift.enable_v6` feature to support migration to the Swift 6 language mode This flag is designed with ease of migration in mind. On toolchains that directly support the Swift 6 language mode (none have been released yet), enabling this feature on a target will simply pass `-swift-version 6` to the compiler. On older compilers however, it will instead pass the equivalent set of `-enable-upcoming-feature` flags as defined inside the compiler. This allows code to begin migrating to Swift 6 mode even before they switch to a Swift 6 toolchain. PiperOrigin-RevId: 629396220 (cherry picked from commit 86f356cc3ab35d02edd3efe972a76e1d0a6a7261 , f1765e6e65ab742e332704717ec7e0129a9b60af, 8065c86800ac18ce6ee0eefe9dac4c0d4c24ef59, and 3cb393fa0bcf8b5e63c875b23ff5779daaf20acd) Signed-off-by: Brentley Jones --- swift/internal/feature_names.bzl | 13 +++++ swift/internal/features.bzl | 57 +++++++++++++++++++++- swift/internal/swift_autoconfiguration.bzl | 20 +++++++- swift/toolchains/config/compile_config.bzl | 12 +++++ swift/toolchains/xcode_swift_toolchain.bzl | 4 ++ 5 files changed, 104 insertions(+), 2 deletions(-) diff --git a/swift/internal/feature_names.bzl b/swift/internal/feature_names.bzl index 76d2c4921..2479f1485 100644 --- a/swift/internal/feature_names.bzl +++ b/swift/internal/feature_names.bzl @@ -30,6 +30,14 @@ SWIFT_FEATURE_DBG = "swift.dbg" SWIFT_FEATURE_FASTBUILD = "swift.fastbuild" SWIFT_FEATURE_OPT = "swift.opt" +# If this feature is enabled, the toolchain should enable the features that are +# available in Swift 6 language mode. If the toolchain supports +# `-swift-version 6`, it will do so using that flag. If it is older, it will +# enable the set of upcoming features that will be on by default in Swift 6, +# allowing users to prepare their code base by opting in to the full set of +# Swift 6 features even before switching to a Swift 6 compiler. +SWIFT_FEATURE_ENABLE_V6 = "swift.enable_v6" + # If True, transitive C headers will be always be passed as inputs to Swift # compilation actions, even when building with explicit modules. SWIFT_FEATURE_HEADERS_ALWAYS_ACTION_INPUTS = "swift.headers_always_action_inputs" @@ -365,6 +373,11 @@ SWIFT_FEATURE_DISABLE_AVAILABILITY_CHECKING = "swift.disable_availability_checki # should never manually, enable, disable, or query this feature. SWIFT_FEATURE__SUPPORTS_UPCOMING_FEATURES = "swift._supports_upcoming_features" +# A private feature that is set by the toolchain if it supports +# `-swift-version 6` (Swift 6.0 and above). Users should never manually enable, +# disable, or query this feature. +SWIFT_FEATURE__SUPPORTS_V6 = "swift._supports_v6" + # Disables Swift sandbox which prevents issues with nested sandboxing when Swift code contains system-provided macros. # If enabled '#Preview' macro provided by SwiftUI fails to build and probably other system-provided macros. # Enabled by default for Swift 5.10+ on macOS. diff --git a/swift/internal/features.bzl b/swift/internal/features.bzl index cf187ff07..5e471c4fe 100644 --- a/swift/internal/features.bzl +++ b/swift/internal/features.bzl @@ -30,6 +30,7 @@ load( "SWIFT_FEATURE_ENABLE_BATCH_MODE", "SWIFT_FEATURE_ENABLE_SKIP_FUNCTION_BODIES", "SWIFT_FEATURE_ENABLE_TESTING", + "SWIFT_FEATURE_ENABLE_V6", "SWIFT_FEATURE_FILE_PREFIX_MAP", "SWIFT_FEATURE_FULL_DEBUG_INFO", "SWIFT_FEATURE_INTERNALIZE_AT_LINK", @@ -39,6 +40,7 @@ load( "SWIFT_FEATURE_REMAP_XCODE_PATH", "SWIFT_FEATURE_USE_GLOBAL_MODULE_CACHE", "SWIFT_FEATURE__FORCE_ALWAYSLINK_TRUE", + "SWIFT_FEATURE__SUPPORTS_V6", ) load(":package_specs.bzl", "label_matches_package_specs") load(":target_triples.bzl", "target_triples") @@ -480,4 +482,57 @@ def _compute_features( # Features that are unsupported by the toolchain override any requests for those features. feature_updater.update_features([], swift_toolchain.unsupported_features) - return (feature_updater.requested_features(), feature_updater.disabled_features()) + all_disabled_features = feature_updater.disabled_features() + all_requested_features = _compute_implied_features( + requested_features = feature_updater.requested_features(), + unsupported_features = all_disabled_features, + ) + return (all_requested_features, all_disabled_features) + +def _compute_implied_features(requested_features, unsupported_features): + """Compute additional features that should be implied by combinations. + + To avoid an explosion of generalized complexity, this is being done only for + features related to language mode support, instead of building it out as a + feature for use elsewhere in the toolchain. + """ + + # If a user requests Swift language mode 6 on a compiler that doesn't + # support `-swift-version 6`, we instead enable all of the upcoming features + # that will be on by default in Swift 6 mode. This provides an early + # migration path for those users. + if (SWIFT_FEATURE_ENABLE_V6 in requested_features and + SWIFT_FEATURE__SUPPORTS_V6 not in requested_features): + for feature in _SWIFT_6_EQUIVALENT_FEATURES: + # Only add it if the user did not explicitly ask for it to be + # suppressed. + if feature not in unsupported_features: + requested_features.append(feature) + + return requested_features + +# The list below is taken from the feature definitions in the compiler, at +# https://github.com/apple/swift/blob/release/6.0/include/swift/Basic/Features.def#L180-L193. +# TODO: b/336996662 - Confirm that this is the final set of features enabled by +# default in Swift 6 language mode when the compiler is released. +_SWIFT_6_EQUIVALENT_FEATURES = [ + "swift.upcoming.ConciseMagicFile", # SE-0274 + "swift.upcoming.ForwardTrailingClosures", # SE-0286 + "swift.upcoming.StrictConcurrency", # SE-0337 + "swift.experimental.StrictConcurrency=complete", # same as above on older compilers + "swift.upcoming.BareSlashRegexLiterals", # SE-0354 + "swift.upcoming.DeprecateApplicationMain", # SE-0383 + "swift.upcoming.ImportObjcForwardDeclarations", # SE-0384 + "swift.upcoming.DisableOutwardActorInference", # SE-0401 + "swift.upcoming.IsolatedDefaultValues", # SE-0411 + "swift.upcoming.GlobalConcurrency", # SE-0412 + "swift.upcoming.InferSendableFromCaptures", # SE-0418 + "swift.upcoming.ImplicitOpenExistentials", # SE-0352 + "swift.upcoming.RegionBasedIsolation", # SE-0414 + "swift.upcoming.DynamicActorIsolation", # SE-0423 + + # The upcoming feature flags only emit warnings about things that will + # become errors in Swift 6. We want the `swift.enable_v6` flag specifically + # to enforce the same error behavior. + "swift.werror.error_in_future_swift_version", +] diff --git a/swift/internal/swift_autoconfiguration.bzl b/swift/internal/swift_autoconfiguration.bzl index e8daf3667..ddfb5bd03 100644 --- a/swift/internal/swift_autoconfiguration.bzl +++ b/swift/internal/swift_autoconfiguration.bzl @@ -36,6 +36,7 @@ load( "SWIFT_FEATURE_USE_AUTOLINK_EXTRACT", "SWIFT_FEATURE_USE_MODULE_WRAP", "SWIFT_FEATURE__SUPPORTS_UPCOMING_FEATURES", + "SWIFT_FEATURE__SUPPORTS_V6", ) load(":toolchain_utils.bzl", "SWIFT_TOOLCHAIN_TYPE") @@ -71,8 +72,24 @@ def _swift_succeeds(repository_ctx, swiftc_path, *args): swift_result = repository_ctx.execute([swiftc_path] + list(args)) return swift_result.return_code == 0 +def _check_supports_language_mode_6(repository_ctx, swiftc_path, _temp_dir): + """Returns True if the swift compiler supports language mode 6.""" + result = repository_ctx.execute([swiftc_path, "-version"]) + if result.return_code == 0: + _, _, almost_version = result.stdout.partition("swiftlang-") + if not almost_version: + return False + + major_version, _, _ = almost_version.parition(".") + if not major_version: + return False + + return int(major_version) >= 6 + + return False + def _check_supports_lld_gc_workaround(repository_ctx, swiftc_path, temp_dir): - """Returns True if lld is being used and it supports nostart-stop-gc""" + """Returns True if lld is being used and it supports nostart-stop-gc.""" source_file = _scratch_file( repository_ctx, temp_dir, @@ -175,6 +192,7 @@ _FEATURE_CHECKS = { SWIFT_FEATURE__SUPPORTS_UPCOMING_FEATURES: ( _check_supports_upcoming_features ), + SWIFT_FEATURE__SUPPORTS_V6: _check_supports_language_mode_6, } def _normalized_linux_cpu(cpu): diff --git a/swift/toolchains/config/compile_config.bzl b/swift/toolchains/config/compile_config.bzl index 59b7aa6b0..ce7cc493a 100644 --- a/swift/toolchains/config/compile_config.bzl +++ b/swift/toolchains/config/compile_config.bzl @@ -53,6 +53,7 @@ load( "SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION", "SWIFT_FEATURE_ENABLE_SKIP_FUNCTION_BODIES", "SWIFT_FEATURE_ENABLE_TESTING", + "SWIFT_FEATURE_ENABLE_V6", "SWIFT_FEATURE_FASTBUILD", "SWIFT_FEATURE_FILE_PREFIX_MAP", "SWIFT_FEATURE_FULL_DEBUG_INFO", @@ -81,6 +82,7 @@ load( "SWIFT_FEATURE_VFSOVERLAY", "SWIFT_FEATURE__NUM_THREADS_0_IN_SWIFTCOPTS", "SWIFT_FEATURE__SUPPORTS_UPCOMING_FEATURES", + "SWIFT_FEATURE__SUPPORTS_V6", "SWIFT_FEATURE__WMO_IN_SWIFTCOPTS", ) load(":action_config.bzl", "ActionConfigInfo", "ConfigResultInfo", "add_arg") @@ -1166,6 +1168,16 @@ def compile_action_configs( SWIFT_FEATURE__SUPPORTS_UPCOMING_FEATURES, ], ), + ActionConfigInfo( + actions = [ + SWIFT_ACTION_COMPILE, + ], + configurators = [add_arg("-swift-version", "6")], + features = [ + SWIFT_FEATURE_ENABLE_V6, + SWIFT_FEATURE__SUPPORTS_V6, + ], + ), ] # NOTE: The positions of these action configs in the list are important, diff --git a/swift/toolchains/xcode_swift_toolchain.bzl b/swift/toolchains/xcode_swift_toolchain.bzl index 85f3307ce..9c3f0c5d6 100644 --- a/swift/toolchains/xcode_swift_toolchain.bzl +++ b/swift/toolchains/xcode_swift_toolchain.bzl @@ -55,6 +55,7 @@ load( "SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD", "SWIFT_FEATURE_REMAP_XCODE_PATH", "SWIFT_FEATURE__SUPPORTS_UPCOMING_FEATURES", + "SWIFT_FEATURE__SUPPORTS_V6", ) load( "//swift/internal:features.bzl", @@ -628,6 +629,9 @@ def _xcode_swift_toolchain_impl(ctx): if _is_xcode_at_least_version(xcode_config, "15.3"): requested_features.append(SWIFT_FEATURE_DISABLE_SWIFT_SANDBOX) + if _is_xcode_at_least_version(xcode_config, "16.0"): + requested_features.append(SWIFT_FEATURE__SUPPORTS_V6) + env = _xcode_env(target_triple = target_triple, xcode_config = xcode_config) execution_requirements = xcode_config.execution_info() generated_header_rewriter = ctx.executable.generated_header_rewriter