Skip to content

Commit 2fbe202

Browse files
committed
Introduce FUTURE_FEATURE definitions for features staged in Swift 6.
Using the same feature set logic as experimental features, provide feature names for "future" features, which are changes that will become available with Swift 6. Use the feature check when determining whether to implementation the feature instead of a language version check, and map existing flags for these features (when available) over to the feature set. As an internal implementation detail, this makes it easier to reason about when specific features are enabled (or not). If we decide to go with piecemeal adoption support for features, it can provide an alternative path to enabling features that feeds this mechanism.
1 parent 7a6f9ce commit 2fbe202

File tree

6 files changed

+63
-5
lines changed

6 files changed

+63
-5
lines changed

include/swift/Basic/Feature.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef SWIFT_BASIC_FEATURES_H
1414
#define SWIFT_BASIC_FEATURES_H
1515

16+
#include "llvm/ADT/Optional.h"
1617
#include "llvm/ADT/StringRef.h"
1718

1819
namespace swift {
@@ -51,10 +52,17 @@ inline bool featureImpliesFeature(Feature feature, Feature implied) {
5152
return (unsigned) feature < (unsigned) implied;
5253
}
5354

55+
/// Get the feature corresponding to this "future" feature, if there is one.
56+
llvm::Optional<Feature> getFutureFeature(llvm::StringRef name);
57+
5458
/// Get the feature corresponding to this "experimental" feature, if there is
5559
/// one.
5660
llvm::Optional<Feature> getExperimentalFeature(llvm::StringRef name);
5761

62+
/// Get the major language version in which this feature was introduced, or
63+
/// \c None if it does not have such a version.
64+
llvm::Optional<unsigned> getFeatureLanguageVersion(Feature feature);
65+
5866
}
5967

6068
#endif // SWIFT_BASIC_FEATURES_H

include/swift/Basic/Features.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@
4848
LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option)
4949
#endif
5050

51+
#ifndef FUTURE_FEATURE
52+
# define FUTURE_FEATURE(FeatureName, SENumber, Version) \
53+
LANGUAGE_FEATURE(FeatureName, SENumber, #FeatureName, \
54+
langOpts.hasFeature(#FeatureName))
55+
#endif
56+
5157
#ifndef EXPERIMENTAL_FEATURE
5258
# define EXPERIMENTAL_FEATURE(FeatureName) \
5359
LANGUAGE_FEATURE(FeatureName, 0, #FeatureName, \
@@ -83,6 +89,8 @@ SUPPRESSIBLE_LANGUAGE_FEATURE(PrimaryAssociatedTypes2, 346, "Primary associated
8389
SUPPRESSIBLE_LANGUAGE_FEATURE(UnavailableFromAsync, 0, "@_unavailableFromAsync", true)
8490
SUPPRESSIBLE_LANGUAGE_FEATURE(NoAsyncAvailability, 340, "@available(*, noasync)", true)
8591

92+
FUTURE_FEATURE(ConciseMagicFile, 274, 6)
93+
8694
EXPERIMENTAL_FEATURE(StaticAssert)
8795
EXPERIMENTAL_FEATURE(VariadicGenerics)
8896
EXPERIMENTAL_FEATURE(NamedOpaqueTypes)
@@ -92,5 +100,6 @@ EXPERIMENTAL_FEATURE(OneWayClosureParameters)
92100
EXPERIMENTAL_FEATURE(TypeWitnessSystemInference)
93101

94102
#undef EXPERIMENTAL_FEATURE
103+
#undef FUTURE_FEATURE
95104
#undef SUPPRESSIBLE_LANGUAGE_FEATURE
96105
#undef LANGUAGE_FEATURE

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2999,6 +2999,10 @@ static bool usesFeatureNoAsyncAvailability(Decl *decl) {
29992999
return decl->getAttrs().getNoAsync(decl->getASTContext()) != nullptr;
30003000
}
30013001

3002+
static bool usesFeatureConciseMagicFile(Decl *decl) {
3003+
return false;
3004+
}
3005+
30023006
static bool usesFeatureVariadicGenerics(Decl *decl) {
30033007
return false;
30043008
}

lib/Basic/LangOptions.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/Config.h"
2424
#include "llvm/ADT/Hashing.h"
2525
#include "llvm/ADT/SmallString.h"
26+
#include "llvm/ADT/StringSwitch.h"
2627
#include "llvm/Support/raw_ostream.h"
2728
#include <limits.h>
2829

@@ -228,10 +229,16 @@ bool LangOptions::hasFeature(Feature feature) const {
228229
if (Features.contains(feature))
229230
return true;
230231

232+
if (auto version = getFeatureLanguageVersion(feature))
233+
return isSwiftVersionAtLeast(*version);
234+
231235
return false;
232236
}
233237

234238
bool LangOptions::hasFeature(llvm::StringRef featureName) const {
239+
if (auto feature = getFutureFeature(featureName))
240+
return hasFeature(*feature);
241+
235242
if (auto feature = getExperimentalFeature(featureName))
236243
return hasFeature(*feature);
237244

@@ -423,6 +430,15 @@ bool swift::isSuppressibleFeature(Feature feature) {
423430
llvm_unreachable("covered switch");
424431
}
425432

433+
llvm::Optional<Feature> swift::getFutureFeature(llvm::StringRef name) {
434+
return llvm::StringSwitch<Optional<Feature>>(name)
435+
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option)
436+
#define FUTURE_FEATURE(FeatureName, SENumber, Version) \
437+
.Case(#FeatureName, Feature::FeatureName)
438+
#include "swift/Basic/Features.def"
439+
.Default(None);
440+
}
441+
426442
llvm::Optional<Feature> swift::getExperimentalFeature(llvm::StringRef name) {
427443
return llvm::StringSwitch<Optional<Feature>>(name)
428444
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option)
@@ -432,6 +448,16 @@ llvm::Optional<Feature> swift::getExperimentalFeature(llvm::StringRef name) {
432448
.Default(None);
433449
}
434450

451+
llvm::Optional<unsigned> swift::getFeatureLanguageVersion(Feature feature) {
452+
switch (feature) {
453+
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option)
454+
#define FUTURE_FEATURE(FeatureName, SENumber, Version) \
455+
case Feature::FeatureName: return Version;
456+
#include "swift/Basic/Features.def"
457+
default: return None;
458+
}
459+
}
460+
435461
DiagnosticBehavior LangOptions::getAccessNoteFailureLimit() const {
436462
switch (AccessNoteBehavior) {
437463
case AccessNoteDiagnosticBehavior::Ignore:

lib/Frontend/CompilerInvocation.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,21 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
632632
Opts.addCustomConditionalCompilationFlag(A->getValue());
633633
}
634634

635+
// Add a future feature if it is not already implied by the language version.
636+
auto addFutureFeatureIfNotImplied = [&](Feature feature) {
637+
// Check if this feature was introduced already in this language version.
638+
if (auto firstVersion = getFeatureLanguageVersion(feature)) {
639+
if (Opts.isSwiftVersionAtLeast(*firstVersion))
640+
return;
641+
}
642+
643+
Opts.Features.insert(feature);
644+
};
645+
646+
// Map historical flags over to future features.
647+
if (Args.hasArg(OPT_enable_experimental_concise_pound_file))
648+
addFutureFeatureIfNotImplied(Feature::ConciseMagicFile);
649+
635650
for (const Arg *A : Args.filtered(OPT_enable_experimental_feature)) {
636651
// If this is a known experimental feature, allow it in +Asserts
637652
// (non-release) builds for testing purposes.
@@ -759,10 +774,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
759774
A->getAsString(Args), A->getValue());
760775
}
761776

762-
Opts.EnableConcisePoundFile =
763-
Args.hasArg(OPT_enable_experimental_concise_pound_file) ||
764-
Opts.EffectiveLanguageVersion.isVersionAtLeast(6);
765-
766777
Opts.EnableCrossImportOverlays =
767778
Args.hasFlag(OPT_enable_cross_import_overlays,
768779
OPT_disable_cross_import_overlays,

lib/Parse/ParseExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,7 @@ getMagicIdentifierLiteralKind(tok Kind, const LangOptions &Opts) {
11141114
switch (Kind) {
11151115
case tok::pound_file:
11161116
// TODO: Enable by default at the next source break. (SR-13199)
1117-
return Opts.EnableConcisePoundFile
1117+
return Opts.hasFeature(Feature::ConciseMagicFile)
11181118
? MagicIdentifierLiteralExpr::FileIDSpelledAsFile
11191119
: MagicIdentifierLiteralExpr::FilePathSpelledAsFile;
11201120
#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) \

0 commit comments

Comments
 (0)