mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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.
This commit is contained in:
@@ -1014,6 +1014,21 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
|
||||
Opts.EnableExperimentalStringProcessing = true;
|
||||
}
|
||||
|
||||
auto enableUpcomingFeature = [&Opts, &Diags](Feature feature) -> bool {
|
||||
// Check if this feature was introduced already in this language version.
|
||||
if (auto firstVersion = getFeatureLanguageVersion(feature)) {
|
||||
if (Opts.isSwiftVersionAtLeast(*firstVersion)) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_upcoming_feature_on_by_default,
|
||||
getFeatureName(feature), *firstVersion);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Opts.enableFeature(feature);
|
||||
return false;
|
||||
};
|
||||
|
||||
// Enable experimental features.
|
||||
for (const Arg *A : Args.filtered(OPT_enable_experimental_feature)) {
|
||||
// Allow StrictConcurrency to have a value that corresponds to the
|
||||
// -strict-concurrency=<blah> settings.
|
||||
@@ -1040,12 +1055,14 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
|
||||
} else {
|
||||
Opts.enableFeature(*feature);
|
||||
}
|
||||
}
|
||||
|
||||
if (*feature == Feature::NoncopyableGenerics2)
|
||||
Opts.enableFeature(Feature::NoncopyableGenerics);
|
||||
|
||||
if (*feature == Feature::IsolatedAny2)
|
||||
Opts.enableFeature(Feature::IsolatedAny);
|
||||
// For compatibility, upcoming features can be enabled with the
|
||||
// -enable-experimental-feature flag too since the feature may have
|
||||
// graduated from being experimental.
|
||||
if (auto feature = getUpcomingFeature(value)) {
|
||||
if (enableUpcomingFeature(*feature))
|
||||
HadError = true;
|
||||
}
|
||||
|
||||
// Hack: In order to support using availability macros in SPM packages, we
|
||||
@@ -1062,24 +1079,15 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
|
||||
}
|
||||
}
|
||||
|
||||
// Map historical flags over to future features.
|
||||
// Enable upcoming features.
|
||||
for (const Arg *A : Args.filtered(OPT_enable_upcoming_feature)) {
|
||||
// Ignore unknown features.
|
||||
auto feature = getUpcomingFeature(A->getValue());
|
||||
if (!feature)
|
||||
continue;
|
||||
|
||||
// Check if this feature was introduced already in this language version.
|
||||
if (auto firstVersion = getFeatureLanguageVersion(*feature)) {
|
||||
if (Opts.isSwiftVersionAtLeast(*firstVersion)) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_upcoming_feature_on_by_default,
|
||||
A->getValue(), *firstVersion);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the feature.
|
||||
Opts.enableFeature(*feature);
|
||||
if (enableUpcomingFeature(*feature))
|
||||
HadError = true;
|
||||
}
|
||||
|
||||
// Map historical flags over to experimental features. We do this for all
|
||||
|
||||
Reference in New Issue
Block a user