Skip to content

Commit d6bb2c0

Browse files
authored
Merge pull request swiftlang#59139 from DougGregor/future-features-impl
2 parents 7a6f9ce + 2cc91d0 commit d6bb2c0

File tree

11 files changed

+95
-36
lines changed

11 files changed

+95
-36
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: 11 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,10 @@ 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+
FUTURE_FEATURE(ForwardTrailingClosures, 286, 6)
94+
FUTURE_FEATURE(BareSlashRegexLiterals, 354, 6)
95+
8696
EXPERIMENTAL_FEATURE(StaticAssert)
8797
EXPERIMENTAL_FEATURE(VariadicGenerics)
8898
EXPERIMENTAL_FEATURE(NamedOpaqueTypes)
@@ -92,5 +102,6 @@ EXPERIMENTAL_FEATURE(OneWayClosureParameters)
92102
EXPERIMENTAL_FEATURE(TypeWitnessSystemInference)
93103

94104
#undef EXPERIMENTAL_FEATURE
105+
#undef FUTURE_FEATURE
95106
#undef SUPPRESSIBLE_LANGUAGE_FEATURE
96107
#undef LANGUAGE_FEATURE

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,9 @@ namespace swift {
354354
/// The set of features that have been enabled.
355355
llvm::SmallSet<Feature, 2> Features;
356356

357+
/// Temporary flag to support LLDB's transition to using \c Features.
358+
bool EnableBareSlashRegexLiterals = false;
359+
357360
/// Use Clang function types for computing canonical types.
358361
/// If this option is false, the clang function types will still be computed
359362
/// but will not be used for checking type equality.
@@ -529,10 +532,6 @@ namespace swift {
529532
/// Enables dumping type witness systems from associated type inference.
530533
bool DumpTypeWitnessSystems = false;
531534

532-
/// Enables `/.../` syntax regular-expression literals. This requires
533-
/// experimental string processing. Note this does not affect `#/.../#`.
534-
bool EnableBareSlashRegexLiterals = false;
535-
536535
/// Sets the target we are building for and updates platform conditions
537536
/// to match.
538537
///

lib/AST/ASTPrinter.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2999,6 +2999,18 @@ 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+
3006+
static bool usesFeatureForwardTrailingClosures(Decl *decl) {
3007+
return false;
3008+
}
3009+
3010+
static bool usesFeatureBareSlashRegexLiterals(Decl *decl) {
3011+
return false;
3012+
}
3013+
30023014
static bool usesFeatureVariadicGenerics(Decl *decl) {
30033015
return false;
30043016
}

lib/Basic/LangOptions.cpp

Lines changed: 30 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,20 @@ bool LangOptions::hasFeature(Feature feature) const {
228229
if (Features.contains(feature))
229230
return true;
230231

232+
if (feature == Feature::BareSlashRegexLiterals &&
233+
EnableBareSlashRegexLiterals)
234+
return true;
235+
236+
if (auto version = getFeatureLanguageVersion(feature))
237+
return isSwiftVersionAtLeast(*version);
238+
231239
return false;
232240
}
233241

234242
bool LangOptions::hasFeature(llvm::StringRef featureName) const {
243+
if (auto feature = getFutureFeature(featureName))
244+
return hasFeature(*feature);
245+
235246
if (auto feature = getExperimentalFeature(featureName))
236247
return hasFeature(*feature);
237248

@@ -423,6 +434,15 @@ bool swift::isSuppressibleFeature(Feature feature) {
423434
llvm_unreachable("covered switch");
424435
}
425436

437+
llvm::Optional<Feature> swift::getFutureFeature(llvm::StringRef name) {
438+
return llvm::StringSwitch<Optional<Feature>>(name)
439+
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option)
440+
#define FUTURE_FEATURE(FeatureName, SENumber, Version) \
441+
.Case(#FeatureName, Feature::FeatureName)
442+
#include "swift/Basic/Features.def"
443+
.Default(None);
444+
}
445+
426446
llvm::Optional<Feature> swift::getExperimentalFeature(llvm::StringRef name) {
427447
return llvm::StringSwitch<Optional<Feature>>(name)
428448
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option)
@@ -432,6 +452,16 @@ llvm::Optional<Feature> swift::getExperimentalFeature(llvm::StringRef name) {
432452
.Default(None);
433453
}
434454

455+
llvm::Optional<unsigned> swift::getFeatureLanguageVersion(Feature feature) {
456+
switch (feature) {
457+
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option)
458+
#define FUTURE_FEATURE(FeatureName, SENumber, Version) \
459+
case Feature::FeatureName: return Version;
460+
#include "swift/Basic/Features.def"
461+
default: return None;
462+
}
463+
}
464+
435465
DiagnosticBehavior LangOptions::getAccessNoteFailureLimit() const {
436466
switch (AccessNoteBehavior) {
437467
case AccessNoteDiagnosticBehavior::Ignore:

lib/Frontend/CompilerInvocation.cpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -486,25 +486,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
486486
= A->getOption().matches(OPT_enable_deserialization_recovery);
487487
}
488488

489-
// Whether '/.../' regex literals are enabled. This implies experimental
490-
// string processing.
491-
if (Args.hasArg(OPT_enable_bare_slash_regex)) {
492-
Opts.EnableBareSlashRegexLiterals = true;
493-
Opts.EnableExperimentalStringProcessing = true;
494-
}
495-
496-
// Experimental string processing.
497-
if (auto A = Args.getLastArg(OPT_enable_experimental_string_processing,
498-
OPT_disable_experimental_string_processing)) {
499-
Opts.EnableExperimentalStringProcessing =
500-
A->getOption().matches(OPT_enable_experimental_string_processing);
501-
502-
// When experimental string processing is explicitly disabled, also disable
503-
// forward slash regex `/.../`.
504-
if (!Opts.EnableExperimentalStringProcessing)
505-
Opts.EnableBareSlashRegexLiterals = false;
506-
}
507-
508489
Opts.EnableExperimentalBoundGenericExtensions |=
509490
Args.hasArg(OPT_enable_experimental_bound_generic_extensions);
510491

@@ -632,6 +613,29 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
632613
Opts.addCustomConditionalCompilationFlag(A->getValue());
633614
}
634615

616+
// Determine whether string processing is enabled
617+
Opts.EnableExperimentalStringProcessing =
618+
Args.hasFlag(OPT_enable_experimental_string_processing,
619+
OPT_disable_experimental_string_processing,
620+
Args.hasArg(OPT_enable_bare_slash_regex));
621+
622+
// Add a future feature if it is not already implied by the language version.
623+
auto addFutureFeatureIfNotImplied = [&](Feature feature) {
624+
// Check if this feature was introduced already in this language version.
625+
if (auto firstVersion = getFeatureLanguageVersion(feature)) {
626+
if (Opts.isSwiftVersionAtLeast(*firstVersion))
627+
return;
628+
}
629+
630+
Opts.Features.insert(feature);
631+
};
632+
633+
// Map historical flags over to future features.
634+
if (Args.hasArg(OPT_enable_experimental_concise_pound_file))
635+
addFutureFeatureIfNotImplied(Feature::ConciseMagicFile);
636+
if (Args.hasArg(OPT_enable_bare_slash_regex))
637+
addFutureFeatureIfNotImplied(Feature::BareSlashRegexLiterals);
638+
635639
for (const Arg *A : Args.filtered(OPT_enable_experimental_feature)) {
636640
// If this is a known experimental feature, allow it in +Asserts
637641
// (non-release) builds for testing purposes.
@@ -759,10 +763,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
759763
A->getAsString(Args), A->getValue());
760764
}
761765

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

lib/Parse/ParseExpr.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,8 @@ UnresolvedDeclRefExpr *Parser::parseExprOperator() {
881881
}
882882

883883
void Parser::tryLexRegexLiteral(bool forUnappliedOperator) {
884-
if (!Context.LangOpts.EnableBareSlashRegexLiterals)
884+
if (!Context.LangOpts.hasFeature(Feature::BareSlashRegexLiterals) ||
885+
!Context.LangOpts.EnableExperimentalStringProcessing)
885886
return;
886887

887888
// Check to see if we have a regex literal `/.../`, optionally with a prefix
@@ -1114,7 +1115,7 @@ getMagicIdentifierLiteralKind(tok Kind, const LangOptions &Opts) {
11141115
switch (Kind) {
11151116
case tok::pound_file:
11161117
// TODO: Enable by default at the next source break. (SR-13199)
1117-
return Opts.EnableConcisePoundFile
1118+
return Opts.hasFeature(Feature::ConciseMagicFile)
11181119
? MagicIdentifierLiteralExpr::FileIDSpelledAsFile
11191120
: MagicIdentifierLiteralExpr::FilePathSpelledAsFile;
11201121
#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) \

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ static bool matchCallArgumentsImpl(
472472
// way to successfully match arguments to parameters.
473473
if (!parameterRequiresArgument(params, paramInfo, paramIdx) &&
474474
!param.getPlainType()->getASTContext().LangOpts
475-
.isSwiftVersionAtLeast(6) &&
475+
.hasFeature(Feature::ForwardTrailingClosures) &&
476476
anyParameterRequiresArgument(
477477
params, paramInfo, paramIdx + 1,
478478
nextArgIdx + 1 < numArgs
@@ -934,7 +934,7 @@ static bool requiresBothTrailingClosureDirections(
934934

935935
// If backward matching is disabled, only scan forward.
936936
ASTContext &ctx = params.front().getPlainType()->getASTContext();
937-
if (ctx.LangOpts.isSwiftVersionAtLeast(6))
937+
if (ctx.LangOpts.hasFeature(Feature::ForwardTrailingClosures))
938938
return false;
939939

940940
// If there are at least two parameters that meet the backward scan's

tools/libSwiftSyntaxParser/libSwiftSyntaxParser.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -512,9 +512,7 @@ swiftparse_client_node_t SynParser::parse(const char *source, size_t len) {
512512

513513
// Always enable bare /.../ regex literal in syntax parser.
514514
langOpts.EnableExperimentalStringProcessing = true;
515-
if (EnableBareSlashRegexLiteral && *EnableBareSlashRegexLiteral) {
516-
langOpts.EnableBareSlashRegexLiterals = true;
517-
}
515+
langOpts.Features.insert(Feature::BareSlashRegexLiterals);
518516
if (EffectiveLanguageVersion) {
519517
langOpts.EffectiveLanguageVersion = *EffectiveLanguageVersion;
520518
}

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4305,7 +4305,7 @@ int main(int argc, char *argv[]) {
43054305
InitInvok.getLangOptions().EnableExperimentalStringProcessing = true;
43064306
}
43074307
if (options::EnableBareSlashRegexLiterals) {
4308-
InitInvok.getLangOptions().EnableBareSlashRegexLiterals = true;
4308+
InitInvok.getLangOptions().Features.insert(Feature::BareSlashRegexLiterals);
43094309
InitInvok.getLangOptions().EnableExperimentalStringProcessing = true;
43104310
}
43114311

tools/swift-syntax-test/swift-syntax-test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ int parseFile(
592592
Invocation.getLangOptions().VerifySyntaxTree = options::VerifySyntaxTree;
593593
Invocation.getLangOptions().DisablePoundIfEvaluation = true;
594594
Invocation.getLangOptions().EnableExperimentalStringProcessing = true;
595-
Invocation.getLangOptions().EnableBareSlashRegexLiterals = true;
595+
Invocation.getLangOptions().Features.insert(Feature::BareSlashRegexLiterals);
596596

597597
Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(InputFileName);
598598

0 commit comments

Comments
 (0)