Skip to content

Commit ad1acd7

Browse files
committed
Frontend: Allow -enable-experimental-feature to specify upcoming features.
During the lifecycle of a feature, it may start as an experimental feature and then graduate to become an upcoming feature. To preserve compatibility with projects that adopted the feature when it was experimental, `-enable-experimental-feature` ought to be able to enable upcoming features, too. Since projects may use `-enable-experimental-feature` for compatibility with an older toolchain that does not have the feature as an upcoming feature, there is no warning when the flag is used to enable an upcoming feature. Note that if the semantics of a feature change when it graduates from experimental to upcoming, then the feature must be renamed so that projects using the experimental feature have an opportunity opt-in to the new semantics of the upcoming feature. Resolves rdar://134276783.
1 parent 4229a91 commit ad1acd7

7 files changed

+31
-21
lines changed

lib/Frontend/CompilerInvocation.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,21 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
10141014
Opts.EnableExperimentalStringProcessing = true;
10151015
}
10161016

1017+
auto enableUpcomingFeature = [&Opts, &Diags](Feature feature) -> bool {
1018+
// Check if this feature was introduced already in this language version.
1019+
if (auto firstVersion = getFeatureLanguageVersion(feature)) {
1020+
if (Opts.isSwiftVersionAtLeast(*firstVersion)) {
1021+
Diags.diagnose(SourceLoc(), diag::error_upcoming_feature_on_by_default,
1022+
getFeatureName(feature), *firstVersion);
1023+
return true;
1024+
}
1025+
}
1026+
1027+
Opts.enableFeature(feature);
1028+
return false;
1029+
};
1030+
1031+
// Enable experimental features.
10171032
for (const Arg *A : Args.filtered(OPT_enable_experimental_feature)) {
10181033
// Allow StrictConcurrency to have a value that corresponds to the
10191034
// -strict-concurrency=<blah> settings.
@@ -1040,12 +1055,14 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
10401055
} else {
10411056
Opts.enableFeature(*feature);
10421057
}
1058+
}
10431059

1044-
if (*feature == Feature::NoncopyableGenerics2)
1045-
Opts.enableFeature(Feature::NoncopyableGenerics);
1046-
1047-
if (*feature == Feature::IsolatedAny2)
1048-
Opts.enableFeature(Feature::IsolatedAny);
1060+
// For compatibility, upcoming features can be enabled with the
1061+
// -enable-experimental-feature flag too since the feature may have
1062+
// graduated from being experimental.
1063+
if (auto feature = getUpcomingFeature(value)) {
1064+
if (enableUpcomingFeature(*feature))
1065+
HadError = true;
10491066
}
10501067

10511068
// Hack: In order to support using availability macros in SPM packages, we
@@ -1062,24 +1079,15 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
10621079
}
10631080
}
10641081

1065-
// Map historical flags over to future features.
1082+
// Enable upcoming features.
10661083
for (const Arg *A : Args.filtered(OPT_enable_upcoming_feature)) {
10671084
// Ignore unknown features.
10681085
auto feature = getUpcomingFeature(A->getValue());
10691086
if (!feature)
10701087
continue;
10711088

1072-
// Check if this feature was introduced already in this language version.
1073-
if (auto firstVersion = getFeatureLanguageVersion(*feature)) {
1074-
if (Opts.isSwiftVersionAtLeast(*firstVersion)) {
1075-
Diags.diagnose(SourceLoc(), diag::error_upcoming_feature_on_by_default,
1076-
A->getValue(), *firstVersion);
1077-
continue;
1078-
}
1079-
}
1080-
1081-
// Add the feature.
1082-
Opts.enableFeature(*feature);
1089+
if (enableUpcomingFeature(*feature))
1090+
HadError = true;
10831091
}
10841092

10851093
// Map historical flags over to experimental features. We do this for all

test/Concurrency/isolated_default_arguments_serialized.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %target-swift-frontend -emit-module -swift-version 5 -emit-module-path %t/SerializedDefaultArguments.swiftmodule -module-name SerializedDefaultArguments -enable-upcoming-feature IsolatedDefaultValues %S/Inputs/serialized_default_arguments.swift
33

44
// RUN: %target-swift-frontend %s -emit-sil -o /dev/null -verify -disable-availability-checking -swift-version 6 -I %t
5-
// RUN: %target-swift-frontend %s -emit-sil -o /dev/null -verify -disable-availability-checking -swift-version 6 -I %t -enable-upcoming-feature RegionBasedIsolation -enable-upcoming-feature IsolatedDefaultValues
5+
// RUN: %target-swift-frontend %s -emit-sil -o /dev/null -verify -disable-availability-checking -swift-version 5 -I %t -enable-upcoming-feature RegionBasedIsolation -enable-upcoming-feature IsolatedDefaultValues -enable-upcoming-feature StrictConcurrency
66

77
// REQUIRES: concurrency
88

test/Concurrency/predates_concurrency_import_swift6.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/NonStrictModule.swiftmodule -module-name NonStrictModule %S/Inputs/NonStrictModule.swift
44

55
// RUN: %target-swift-frontend -swift-version 6 -I %t %s -emit-sil -o /dev/null -verify -parse-as-library
6-
// RUN: %target-swift-frontend -swift-version 6 -I %t %s -emit-sil -o /dev/null -verify -enable-upcoming-feature RegionBasedIsolation -parse-as-library
76

87
@preconcurrency import NonStrictModule
98
@preconcurrency import StrictModule

test/Concurrency/property_initializers_swift6.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// RUN: %target-swift-frontend -swift-version 6 -disable-availability-checking -strict-concurrency=complete -emit-sil -o /dev/null -verify %s
2-
// RUN: %target-swift-frontend -swift-version 6 -disable-availability-checking -strict-concurrency=complete -emit-sil -o /dev/null -verify %s -enable-upcoming-feature RegionBasedIsolation
32

43
// REQUIRES: concurrency
54

test/Frontend/upcoming_feature.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212
// RUN: %target-swift-frontend -typecheck -enable-upcoming-feature ConciseMagicFile -enable-upcoming-feature UnknownFeature %s
1313
// RUN: %target-swift-frontend -typecheck -enable-upcoming-feature UnknownFeature -enable-upcoming-feature ConciseMagicFile %s
1414

15+
// For compatibility when a feature graduates, it's fine to refer to an
16+
// upcoming feature as an experimental feature.
17+
// RUN: %target-swift-frontend -typecheck -enable-experimental-feature ConciseMagicFile %s
1518

1619
// It's not fine to provide a feature that's in the specified language version.
1720
// RUN: not %target-swift-frontend -typecheck -enable-upcoming-feature ConciseMagicFile -swift-version 6 %s 2>&1 | %FileCheck %s
21+
// RUN: not %target-swift-frontend -typecheck -enable-experimental-feature ConciseMagicFile -swift-version 6 %s 2>&1 | %FileCheck %s
1822

1923
// CHECK: error: upcoming feature 'ConciseMagicFile' is already enabled as of Swift version 6
2024

test/Sema/access-level-import-flag-check.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
// RUN: %target-swift-frontend -typecheck %t/ClientWithoutTheFlag.swift -I %t \
2020
// RUN: -enable-upcoming-feature InternalImportsByDefault \
2121
// RUN: -package-name package -verify
22-
// REQUIRES: asserts
2322

2423
/// swiftinterfaces don't need the flag.
2524
// RUN: %target-swift-typecheck-module-from-interface(%t/Client.swiftinterface) -I %t

test/type/explicit_existential.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %target-typecheck-verify-swift -verify-additional-prefix default-swift-mode-
22
// RUN: %target-typecheck-verify-swift -swift-version 6 -verify-additional-prefix swift-6-
33
// RUN: %target-typecheck-verify-swift -enable-upcoming-feature ExistentialAny -verify-additional-prefix explicit-any- -verify-additional-prefix default-swift-mode-
4+
// RUN: %target-typecheck-verify-swift -enable-experimental-feature ExistentialAny -verify-additional-prefix explicit-any- -verify-additional-prefix default-swift-mode-
45

56

67
protocol HasSelfRequirements {

0 commit comments

Comments
 (0)