Skip to content

Commit 7f32376

Browse files
committed
Make Feature a struct enum so we can put methods on it.
Just noticed this as I was looking at making other changes.
1 parent 4c60e03 commit 7f32376

File tree

15 files changed

+111
-91
lines changed

15 files changed

+111
-91
lines changed

include/swift/Basic/Feature.h

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#ifndef SWIFT_BASIC_FEATURES_H
14-
#define SWIFT_BASIC_FEATURES_H
13+
#ifndef SWIFT_BASIC_FEATURE_H
14+
#define SWIFT_BASIC_FEATURE_H
15+
16+
#include "swift/Basic/LLVM.h"
1517

1618
#include "llvm/ADT/StringRef.h"
1719
#include <optional>
@@ -21,53 +23,71 @@ namespace swift {
2123
class LangOptions;
2224

2325
/// Enumeration describing all of the named features.
24-
enum class Feature : uint16_t {
26+
struct Feature {
27+
enum class InnerKind : uint16_t {
2528
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) FeatureName,
2629
#include "swift/Basic/Features.def"
27-
};
30+
};
31+
32+
InnerKind kind;
2833

29-
constexpr unsigned numFeatures() {
30-
enum Features {
34+
constexpr Feature(InnerKind kind) : kind(kind) {}
35+
constexpr Feature(unsigned inputKind) : kind(InnerKind(inputKind)) {}
36+
37+
constexpr operator InnerKind() const { return kind; }
38+
constexpr explicit operator unsigned() const { return unsigned(kind); }
39+
constexpr explicit operator size_t() const { return size_t(kind); }
40+
41+
static constexpr unsigned getNumFeatures() {
42+
enum Features {
3143
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) FeatureName,
3244
#include "swift/Basic/Features.def"
33-
NumFeatures
34-
};
35-
return NumFeatures;
36-
}
45+
NumFeatures
46+
};
47+
return NumFeatures;
48+
}
3749

38-
/// Check whether the given feature is available in production compilers.
39-
bool isFeatureAvailableInProduction(Feature feature);
50+
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
51+
static const Feature FeatureName;
52+
#include "swift/Basic/Features.def"
4053

41-
/// Determine the in-source name of the given feature.
42-
llvm::StringRef getFeatureName(Feature feature);
54+
/// Check whether the given feature is available in production compilers.
55+
bool isAvailableInProduction() const;
4356

44-
/// Determine whether the first feature is more recent (and thus implies
45-
/// the existence of) the second feature. Only meaningful for suppressible
46-
/// features.
47-
inline bool featureImpliesFeature(Feature feature, Feature implied) {
48-
// Suppressible features are expected to be listed in order of
49-
// addition in Features.def.
50-
return (unsigned) feature < (unsigned) implied;
51-
}
57+
/// Determine the in-source name of the given feature.
58+
llvm::StringRef getName() const;
5259

53-
/// Get the feature corresponding to this "future" feature, if there is one.
54-
std::optional<Feature> getUpcomingFeature(llvm::StringRef name);
60+
/// Determine whether the given feature supports adoption mode.
61+
bool isAdoptable() const;
5562

56-
/// Get the feature corresponding to this "experimental" feature, if there is
57-
/// one.
58-
std::optional<Feature> getExperimentalFeature(llvm::StringRef name);
63+
/// Determine whether this feature should be included in the
64+
/// module interface
65+
bool includeInModuleInterface() const;
5966

60-
/// Get the major language version in which this feature was introduced, or
61-
/// \c None if it does not have such a version.
62-
std::optional<unsigned> getFeatureLanguageVersion(Feature feature);
67+
/// Determine whether the first feature is more recent (and thus implies
68+
/// the existence of) the second feature. Only meaningful for suppressible
69+
/// features.
70+
constexpr bool featureImpliesFeature(Feature implied) const {
71+
// Suppressible features are expected to be listed in order of
72+
// addition in Features.def.
73+
return (unsigned)kind < (unsigned)implied.kind;
74+
}
6375

64-
/// Determine whether the given feature supports adoption mode.
65-
bool isFeatureAdoptable(Feature feature);
76+
/// Get the feature corresponding to this "future" feature, if there is one.
77+
static std::optional<Feature> getUpcomingFeature(StringRef name);
6678

67-
/// Determine whether this feature should be included in the
68-
/// module interface
69-
bool includeInModuleInterface(Feature feature);
79+
/// Get the feature corresponding to this "experimental" feature, if there is
80+
/// one.
81+
static std::optional<Feature> getExperimentalFeature(StringRef name);
7082

83+
/// Get the major language version in which this feature was introduced, or
84+
/// \c None if it does not have such a version.
85+
std::optional<unsigned> getLanguageVersion() const;
86+
};
87+
88+
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
89+
constexpr Feature Feature::FeatureName = Feature::InnerKind::FeatureName;
90+
#include "swift/Basic/Features.def"
7191
}
7292

7393
#endif // SWIFT_BASIC_FEATURES_H

include/swift/Basic/LangOptions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,8 +809,9 @@ namespace swift {
809809
llvm::SmallVector<std::string, 2> CustomConditionalCompilationFlags;
810810

811811
public:
812+
//==========================================================================
812813
// MARK: Features
813-
// =========================================================================
814+
//==========================================================================
814815

815816
/// A wrapper around the feature state enumeration.
816817
struct FeatureState {

include/swift/SILOptimizer/OptimizerBridgingImpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ bool BridgedPassContext::enableStackProtection() const {
545545

546546
bool BridgedPassContext::hasFeature(BridgedFeature feature) const {
547547
swift::SILModule *mod = invocation->getPassManager()->getModule();
548-
return mod->getASTContext().LangOpts.hasFeature((swift::Feature)feature);
548+
return mod->getASTContext().LangOpts.hasFeature(swift::Feature(feature));
549549
}
550550

551551
bool BridgedPassContext::enableMoveInoutStackProtection() const {

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3297,7 +3297,7 @@ static void printCompatibilityCheckIf(ASTPrinter &printer, bool isElseIf,
32973297
} else {
32983298
first = false;
32993299
}
3300-
printer << "$" << getFeatureName(feature);
3300+
printer << "$" << Feature(feature).getName();
33013301
}
33023302

33033303
#ifndef NDEBUG

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ void FeatureSet::collectRequiredFeature(Feature feature,
515515

516516
void FeatureSet::collectSuppressibleFeature(Feature feature,
517517
InsertOrRemove operation) {
518-
suppressible.insertOrRemove(numFeatures() - size_t(feature),
518+
suppressible.insertOrRemove(Feature::getNumFeatures() - size_t(feature),
519519
operation == Insert);
520520
}
521521

lib/AST/FeatureSet.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919

2020
namespace swift {
2121

22-
using BasicFeatureSet = FixedBitSet<numFeatures(), Feature>;
22+
using BasicFeatureSet =
23+
FixedBitSet<Feature::getNumFeatures(), Feature::InnerKind>;
2324

2425
class FeatureSet {
2526
BasicFeatureSet required;
@@ -30,7 +31,7 @@ class FeatureSet {
3031
// This is the easiest way of letting us iterate from largest to
3132
// smallest, i.e. from the newest to the oldest feature, which is
3233
// the order in which we need to emit #if clauses.
33-
using SuppressibleFeatureSet = FixedBitSet<numFeatures(), size_t>;
34+
using SuppressibleFeatureSet = FixedBitSet<Feature::getNumFeatures(), size_t>;
3435
SuppressibleFeatureSet suppressible;
3536

3637
public:
@@ -42,7 +43,7 @@ class FeatureSet {
4243

4344
public:
4445
bool empty() const { return i == e; }
45-
Feature next() { return Feature(numFeatures() - *i++); }
46+
Feature next() { return Feature(Feature::getNumFeatures() - *i++); }
4647
};
4748

4849
bool empty() const { return required.empty() && suppressible.empty(); }

lib/Basic/Feature.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
using namespace swift;
1818

19-
bool swift::isFeatureAvailableInProduction(Feature feature) {
20-
switch (feature) {
19+
bool Feature::isAvailableInProduction() const {
20+
switch (kind) {
2121
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
2222
case Feature::FeatureName: \
2323
return true;
@@ -29,8 +29,8 @@ bool swift::isFeatureAvailableInProduction(Feature feature) {
2929
llvm_unreachable("covered switch");
3030
}
3131

32-
llvm::StringRef swift::getFeatureName(Feature feature) {
33-
switch (feature) {
32+
llvm::StringRef Feature::getName() const {
33+
switch (kind) {
3434
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
3535
case Feature::FeatureName: \
3636
return #FeatureName;
@@ -39,7 +39,7 @@ llvm::StringRef swift::getFeatureName(Feature feature) {
3939
llvm_unreachable("covered switch");
4040
}
4141

42-
std::optional<Feature> swift::getUpcomingFeature(llvm::StringRef name) {
42+
std::optional<Feature> Feature::getUpcomingFeature(llvm::StringRef name) {
4343
return llvm::StringSwitch<std::optional<Feature>>(name)
4444
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description)
4545
#define UPCOMING_FEATURE(FeatureName, SENumber, Version) \
@@ -48,7 +48,7 @@ std::optional<Feature> swift::getUpcomingFeature(llvm::StringRef name) {
4848
.Default(std::nullopt);
4949
}
5050

51-
std::optional<Feature> swift::getExperimentalFeature(llvm::StringRef name) {
51+
std::optional<Feature> Feature::getExperimentalFeature(llvm::StringRef name) {
5252
return llvm::StringSwitch<std::optional<Feature>>(name)
5353
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description)
5454
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \
@@ -57,8 +57,8 @@ std::optional<Feature> swift::getExperimentalFeature(llvm::StringRef name) {
5757
.Default(std::nullopt);
5858
}
5959

60-
std::optional<unsigned> swift::getFeatureLanguageVersion(Feature feature) {
61-
switch (feature) {
60+
std::optional<unsigned> Feature::getLanguageVersion() const {
61+
switch (kind) {
6262
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description)
6363
#define UPCOMING_FEATURE(FeatureName, SENumber, Version) \
6464
case Feature::FeatureName: \
@@ -69,8 +69,8 @@ std::optional<unsigned> swift::getFeatureLanguageVersion(Feature feature) {
6969
}
7070
}
7171

72-
bool swift::isFeatureAdoptable(Feature feature) {
73-
switch (feature) {
72+
bool Feature::isAdoptable() const {
73+
switch (kind) {
7474
#define ADOPTABLE_UPCOMING_FEATURE(FeatureName, SENumber, Version)
7575
#define ADOPTABLE_EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd)
7676
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
@@ -87,8 +87,8 @@ bool swift::isFeatureAdoptable(Feature feature) {
8787
}
8888
}
8989

90-
bool swift::includeInModuleInterface(Feature feature) {
91-
switch (feature) {
90+
bool Feature::includeInModuleInterface() const {
91+
switch (kind) {
9292
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
9393
case Feature::FeatureName: \
9494
return true;

lib/Basic/LangOptions.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -295,18 +295,17 @@ bool LangOptions::isCustomConditionalCompilationFlagSet(StringRef Name) const {
295295
}
296296

297297
bool LangOptions::FeatureState::isEnabled() const {
298-
return this->state == FeatureState::Kind::Enabled;
298+
return state == FeatureState::Kind::Enabled;
299299
}
300300

301301
bool LangOptions::FeatureState::isEnabledForAdoption() const {
302-
ASSERT(isFeatureAdoptable(this->feature) &&
303-
"You forgot to make the feature adoptable!");
302+
ASSERT(feature.isAdoptable() && "You forgot to make the feature adoptable!");
304303

305-
return this->state == FeatureState::Kind::EnabledForAdoption;
304+
return state == FeatureState::Kind::EnabledForAdoption;
306305
}
307306

308307
LangOptions::FeatureStateStorage::FeatureStateStorage()
309-
: states(numFeatures(), FeatureState::Kind::Off) {}
308+
: states(Feature::getNumFeatures(), FeatureState::Kind::Off) {}
310309

311310
void LangOptions::FeatureStateStorage::setState(Feature feature,
312311
FeatureState::Kind state) {
@@ -323,12 +322,12 @@ LangOptions::FeatureStateStorage::getState(Feature feature) const {
323322
}
324323

325324
LangOptions::FeatureState LangOptions::getFeatureState(Feature feature) const {
326-
auto state = this->featureStates.getState(feature);
325+
auto state = featureStates.getState(feature);
327326
if (state.isEnabled())
328327
return state;
329328

330-
if (auto version = getFeatureLanguageVersion(feature)) {
331-
if (this->isSwiftVersionAtLeast(*version)) {
329+
if (auto version = feature.getLanguageVersion()) {
330+
if (isSwiftVersionAtLeast(*version)) {
332331
return FeatureState(feature, FeatureState::Kind::Enabled);
333332
}
334333
}
@@ -340,7 +339,7 @@ bool LangOptions::hasFeature(Feature feature) const {
340339
if (this->featureStates.getState(feature).isEnabled())
341340
return true;
342341

343-
if (auto version = getFeatureLanguageVersion(feature))
342+
if (auto version = feature.getLanguageVersion())
344343
return isSwiftVersionAtLeast(*version);
345344

346345
return false;
@@ -360,12 +359,12 @@ bool LangOptions::hasFeature(llvm::StringRef featureName) const {
360359

361360
void LangOptions::enableFeature(Feature feature, bool forAdoption) {
362361
if (forAdoption) {
363-
ASSERT(isFeatureAdoptable(feature));
364-
this->featureStates.setState(feature,
365-
FeatureState::Kind::EnabledForAdoption);
366-
} else {
367-
this->featureStates.setState(feature, FeatureState::Kind::Enabled);
362+
ASSERT(feature.isAdoptable());
363+
featureStates.setState(feature, FeatureState::Kind::EnabledForAdoption);
364+
return;
368365
}
366+
367+
featureStates.setState(feature, FeatureState::Kind::Enabled);
369368
}
370369

371370
void LangOptions::disableFeature(Feature feature) {

lib/DriverTool/sil_opt_main.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -749,14 +749,14 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
749749
}
750750

751751
for (auto &featureName : options.UpcomingFeatures) {
752-
auto feature = getUpcomingFeature(featureName);
752+
auto feature = Feature::getUpcomingFeature(featureName);
753753
if (!feature) {
754754
llvm::errs() << "error: unknown upcoming feature "
755755
<< QuotedString(featureName) << "\n";
756756
exit(-1);
757757
}
758758

759-
if (auto firstVersion = getFeatureLanguageVersion(*feature)) {
759+
if (auto firstVersion = feature->getLanguageVersion()) {
760760
if (Invocation.getLangOptions().isSwiftVersionAtLeast(*firstVersion)) {
761761
llvm::errs() << "error: upcoming feature " << QuotedString(featureName)
762762
<< " is already enabled as of Swift version "
@@ -768,7 +768,7 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
768768
}
769769

770770
for (auto &featureName : options.ExperimentalFeatures) {
771-
if (auto feature = getExperimentalFeature(featureName)) {
771+
if (auto feature = Feature::getExperimentalFeature(featureName)) {
772772
Invocation.getLangOptions().enableFeature(*feature);
773773
} else {
774774
llvm::errs() << "error: unknown experimental feature "

0 commit comments

Comments
 (0)