Skip to content

Commit 02d5210

Browse files
committed
[ModuleInterface] Add mechanism to exclude experimental flags from the module interface
rdar://109722548
1 parent 4920e4a commit 02d5210

File tree

5 files changed

+79
-38
lines changed

5 files changed

+79
-38
lines changed

include/swift/Basic/Feature.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ llvm::Optional<Feature> getExperimentalFeature(llvm::StringRef name);
6666
/// \c None if it does not have such a version.
6767
llvm::Optional<unsigned> getFeatureLanguageVersion(Feature feature);
6868

69+
/// Determine whether this feature should be included in the
70+
/// module interface
71+
bool includeInModuleInterface(Feature feature);
72+
6973
}
7074

7175
#endif // SWIFT_BASIC_FEATURES_H

include/swift/Basic/Features.def

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
#ifndef EXPERIMENTAL_FEATURE
5858
// Warning: setting `AvailableInProd` to `true` on a feature means that the flag
5959
// cannot be dropped in the future.
60-
# define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \
60+
# define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd, IncludeInModuleInterface) \
6161
LANGUAGE_FEATURE(FeatureName, 0, #FeatureName, \
6262
langOpts.hasFeature(#FeatureName))
6363
#endif
@@ -109,92 +109,92 @@ UPCOMING_FEATURE(BareSlashRegexLiterals, 354, 6)
109109
UPCOMING_FEATURE(ExistentialAny, 335, 6)
110110
UPCOMING_FEATURE(ImportObjcForwardDeclarations, 384, 6)
111111

112-
EXPERIMENTAL_FEATURE(StaticAssert, false)
113-
EXPERIMENTAL_FEATURE(VariadicGenerics, false)
114-
EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false)
115-
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false)
116-
EXPERIMENTAL_FEATURE(FreestandingMacros, true)
117-
EXPERIMENTAL_FEATURE(CodeItemMacros, true)
118-
EXPERIMENTAL_FEATURE(TupleConformances, false)
112+
EXPERIMENTAL_FEATURE(StaticAssert, false, true)
113+
EXPERIMENTAL_FEATURE(VariadicGenerics, false, true)
114+
EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false, true)
115+
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false, true)
116+
EXPERIMENTAL_FEATURE(FreestandingMacros, true, true)
117+
EXPERIMENTAL_FEATURE(CodeItemMacros, true, true)
118+
EXPERIMENTAL_FEATURE(TupleConformances, false, true)
119119

120120
// FIXME: MoveOnlyClasses is not intended to be in production,
121121
// but our tests currently rely on it, and we want to run those
122122
// tests in non-asserts builds too.
123-
EXPERIMENTAL_FEATURE(MoveOnlyClasses, true)
124-
EXPERIMENTAL_FEATURE(NoImplicitCopy, true)
125-
EXPERIMENTAL_FEATURE(OldOwnershipOperatorSpellings, true)
126-
EXPERIMENTAL_FEATURE(MoveOnlyEnumDeinits, true)
127-
EXPERIMENTAL_FEATURE(MoveOnlyTuples, true)
123+
EXPERIMENTAL_FEATURE(MoveOnlyClasses, true, true)
124+
EXPERIMENTAL_FEATURE(NoImplicitCopy, true, true)
125+
EXPERIMENTAL_FEATURE(OldOwnershipOperatorSpellings, true, true)
126+
EXPERIMENTAL_FEATURE(MoveOnlyEnumDeinits, true, true)
127+
EXPERIMENTAL_FEATURE(MoveOnlyTuples, true, true)
128128

129-
EXPERIMENTAL_FEATURE(OneWayClosureParameters, false)
130-
EXPERIMENTAL_FEATURE(TypeWitnessSystemInference, false)
131-
EXPERIMENTAL_FEATURE(LayoutPrespecialization, true)
129+
EXPERIMENTAL_FEATURE(OneWayClosureParameters, false, true)
130+
EXPERIMENTAL_FEATURE(TypeWitnessSystemInference, false, true)
131+
EXPERIMENTAL_FEATURE(LayoutPrespecialization, true, true)
132132

133-
EXPERIMENTAL_FEATURE(ModuleInterfaceExportAs, true)
134-
EXPERIMENTAL_FEATURE(AccessLevelOnImport, true)
133+
EXPERIMENTAL_FEATURE(ModuleInterfaceExportAs, true, true)
134+
EXPERIMENTAL_FEATURE(AccessLevelOnImport, true, true)
135135

136136
/// Whether to enable experimental layout string value witnesses
137-
EXPERIMENTAL_FEATURE(LayoutStringValueWitnesses, true)
138-
EXPERIMENTAL_FEATURE(LayoutStringValueWitnessesInstantiation, true)
137+
EXPERIMENTAL_FEATURE(LayoutStringValueWitnesses, true, false)
138+
EXPERIMENTAL_FEATURE(LayoutStringValueWitnessesInstantiation, true, false)
139139

140140
/// Whether to enable experimental differentiable programming features:
141141
/// `@differentiable` declaration attribute, etc.
142-
EXPERIMENTAL_FEATURE(DifferentiableProgramming, false)
142+
EXPERIMENTAL_FEATURE(DifferentiableProgramming, false, true)
143143

144144
/// Whether to enable forward mode differentiation.
145-
EXPERIMENTAL_FEATURE(ForwardModeDifferentiation, false)
145+
EXPERIMENTAL_FEATURE(ForwardModeDifferentiation, false, true)
146146

147147
/// Whether to enable experimental `AdditiveArithmetic` derived
148148
/// conformances.
149-
EXPERIMENTAL_FEATURE(AdditiveArithmeticDerivedConformances, false)
149+
EXPERIMENTAL_FEATURE(AdditiveArithmeticDerivedConformances, false, true)
150150

151151
/// Whether Objective-C completion handler parameters are imported as
152152
/// @Sendable.
153-
EXPERIMENTAL_FEATURE(SendableCompletionHandlers, false)
153+
EXPERIMENTAL_FEATURE(SendableCompletionHandlers, false, true)
154154

155155
/// Enables opaque type erasure without also enabling implict dynamic
156-
EXPERIMENTAL_FEATURE(OpaqueTypeErasure, false)
156+
EXPERIMENTAL_FEATURE(OpaqueTypeErasure, false, true)
157157

158158
/// Whether to perform round-trip testing of the Swift Swift parser.
159-
EXPERIMENTAL_FEATURE(ParserRoundTrip, false)
159+
EXPERIMENTAL_FEATURE(ParserRoundTrip, false, true)
160160

161161
/// Whether to perform validation of the parse tree produced by the Swift
162162
/// Swift parser.
163-
EXPERIMENTAL_FEATURE(ParserValidation, false)
163+
EXPERIMENTAL_FEATURE(ParserValidation, false, true)
164164

165165
/// Whether to emit diagnostics from the new parser first, and only emit
166166
/// diagnostics from the existing parser when there are none from the new
167167
/// parser.
168-
EXPERIMENTAL_FEATURE(ParserDiagnostics, false)
168+
EXPERIMENTAL_FEATURE(ParserDiagnostics, false, true)
169169

170170
/// Enables implicit some while also enabling existential `any`
171-
EXPERIMENTAL_FEATURE(ImplicitSome, false)
171+
EXPERIMENTAL_FEATURE(ImplicitSome, false, true)
172172

173173
/// Parse using the Swift (swift-syntax) parser and use ASTGen to generate the
174174
/// corresponding syntax tree.
175-
EXPERIMENTAL_FEATURE(ParserASTGen, false)
175+
EXPERIMENTAL_FEATURE(ParserASTGen, false, true)
176176

177177
/// Parse using the Swift (swift-syntax) parser and use ASTGen to generate the
178178
/// corresponding syntax tree.
179-
EXPERIMENTAL_FEATURE(BuiltinMacros, false)
179+
EXPERIMENTAL_FEATURE(BuiltinMacros, false, true)
180180

181181
/// Whether to enable experimental @runtimeMetadata feature which allows to
182182
/// declare an attribute which is discoverable and constructable at runtime.
183-
EXPERIMENTAL_FEATURE(RuntimeDiscoverableAttrs, false)
183+
EXPERIMENTAL_FEATURE(RuntimeDiscoverableAttrs, false, true)
184184

185185
/// Import C++ class templates as semantically-meaningless symbolic
186186
/// Swift types and C++ methods as symbolic functions with blank
187187
/// signatures.
188-
EXPERIMENTAL_FEATURE(ImportSymbolicCXXDecls, false)
188+
EXPERIMENTAL_FEATURE(ImportSymbolicCXXDecls, false, true)
189189

190190
/// Generate bindings for functions that 'throw' in the C++ section of the generated Clang header.
191-
EXPERIMENTAL_FEATURE(GenerateBindingsForThrowingFunctionsInCXX, false)
191+
EXPERIMENTAL_FEATURE(GenerateBindingsForThrowingFunctionsInCXX, false, true)
192192

193193
/// Enable reference bindings.
194-
EXPERIMENTAL_FEATURE(ReferenceBindings, false)
194+
EXPERIMENTAL_FEATURE(ReferenceBindings, false, true)
195195

196196
/// Enable the explicit 'import Builtin' and allow Builtin usage.
197-
EXPERIMENTAL_FEATURE(BuiltinModule, true)
197+
EXPERIMENTAL_FEATURE(BuiltinModule, true, true)
198198

199199
#undef EXPERIMENTAL_FEATURE
200200
#undef UPCOMING_FEATURE

lib/Basic/LangOptions.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ bool swift::isFeatureAvailableInProduction(Feature feature) {
489489
switch (feature) {
490490
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option) \
491491
case Feature::FeatureName: return true;
492-
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \
492+
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd, IncludeInModuleInterface) \
493493
case Feature::FeatureName: return AvailableInProd;
494494
#include "swift/Basic/Features.def"
495495
}
@@ -508,7 +508,7 @@ llvm::Optional<Feature> swift::getUpcomingFeature(llvm::StringRef name) {
508508
llvm::Optional<Feature> swift::getExperimentalFeature(llvm::StringRef name) {
509509
return llvm::StringSwitch<Optional<Feature>>(name)
510510
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option)
511-
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \
511+
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd, IncludeInModuleInterface) \
512512
.Case(#FeatureName, Feature::FeatureName)
513513
#include "swift/Basic/Features.def"
514514
.Default(None);
@@ -524,6 +524,17 @@ llvm::Optional<unsigned> swift::getFeatureLanguageVersion(Feature feature) {
524524
}
525525
}
526526

527+
bool swift::includeInModuleInterface(Feature feature) {
528+
switch (feature) {
529+
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option) \
530+
case Feature::FeatureName: return true;
531+
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd, IncludeInModuleInterface) \
532+
case Feature::FeatureName: return IncludeInModuleInterface;
533+
#include "swift/Basic/Features.def"
534+
}
535+
llvm_unreachable("covered switch");
536+
}
537+
527538
DiagnosticBehavior LangOptions::getAccessNoteFailureLimit() const {
528539
switch (AccessNoteBehavior) {
529540
case AccessNoteDiagnosticBehavior::Ignore:

lib/Frontend/CompilerInvocation.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,19 @@ static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
417417
}
418418
}
419419

420+
/// Checks if an arg is generally allowed to be included
421+
/// in a module interface
422+
static bool ShouldIncludeModuleInterfaceArg(const Arg *A) {
423+
if (!A->getOption().matches(options::OPT_enable_experimental_feature))
424+
return true;
425+
426+
if (auto feature = getExperimentalFeature(A->getValue())) {
427+
return swift::includeInModuleInterface(*feature);
428+
}
429+
430+
return true;
431+
}
432+
420433
/// Save a copy of any flags marked as ModuleInterfaceOption, if running
421434
/// in a mode that is going to emit a .swiftinterface file.
422435
static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
@@ -428,6 +441,9 @@ static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
428441
ArgStringList RenderedArgsIgnorable;
429442
ArgStringList RenderedArgsIgnorablePrivate;
430443
for (auto A : Args) {
444+
if (!ShouldIncludeModuleInterfaceArg(A))
445+
continue;
446+
431447
if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorablePrivate)) {
432448
A->render(Args, RenderedArgsIgnorablePrivate);
433449
} else if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorable)) {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -enable-library-evolution -emit-module-interface-path %t.swiftinterface -module-name t %s -target-min-inlining-version 42 -emit-module -o /dev/null -O -enable-experimental-feature LayoutStringValueWitnesses -enable-experimental-feature LayoutStringValueWitnessesInstantiation
4+
// RUN: %FileCheck %s < %t.swiftinterface -check-prefix=CHECK-SWIFTINTERFACE
5+
//
6+
// CHECK-SWIFTINTERFACE: swift-module-flags-ignorable:
7+
// CHECK-SWIFTINTERFACE-NOT: -enable-experimental-feature LayoutStringValueWitnesses
8+
// CHECK-SWIFTINTERFACE-NOT: -enable-experimental-feature LayoutStringValueWitnessesInstantiation
9+
10+
public func foo() { }

0 commit comments

Comments
 (0)