diff --git a/include/swift/Basic/Feature.h b/include/swift/Basic/Feature.h index 26790df478d02..5a4bad225e6bd 100644 --- a/include/swift/Basic/Feature.h +++ b/include/swift/Basic/Feature.h @@ -66,6 +66,10 @@ llvm::Optional getExperimentalFeature(llvm::StringRef name); /// \c None if it does not have such a version. llvm::Optional getFeatureLanguageVersion(Feature feature); +/// Determine whether this feature should be included in the +/// module interface +bool includeInModuleInterface(Feature feature); + } #endif // SWIFT_BASIC_FEATURES_H diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index d5a4ea4445de9..d678b2763910b 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -62,6 +62,11 @@ langOpts.hasFeature(#FeatureName)) #endif +#ifndef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE +# define EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE(FeatureName, AvailableInProd) \ + EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) +#endif + LANGUAGE_FEATURE(AsyncAwait, 296, "async/await", true) LANGUAGE_FEATURE(EffectfulProp, 310, "Effectful properties", true) LANGUAGE_FEATURE(MarkerProtocol, 0, "@_marker protocol", true) @@ -133,8 +138,8 @@ EXPERIMENTAL_FEATURE(ModuleInterfaceExportAs, true) EXPERIMENTAL_FEATURE(AccessLevelOnImport, true) /// Whether to enable experimental layout string value witnesses -EXPERIMENTAL_FEATURE(LayoutStringValueWitnesses, true) -EXPERIMENTAL_FEATURE(LayoutStringValueWitnessesInstantiation, true) +EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE(LayoutStringValueWitnesses, true) +EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE(LayoutStringValueWitnessesInstantiation, true) /// Whether to enable experimental differentiable programming features: /// `@differentiable` declaration attribute, etc. @@ -195,6 +200,7 @@ EXPERIMENTAL_FEATURE(ReferenceBindings, false) /// Enable the explicit 'import Builtin' and allow Builtin usage. EXPERIMENTAL_FEATURE(BuiltinModule, true) +#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE #undef EXPERIMENTAL_FEATURE #undef UPCOMING_FEATURE #undef SUPPRESSIBLE_LANGUAGE_FEATURE diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index 48595776a27d7..01104570212dc 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -485,7 +485,7 @@ bool swift::isFeatureAvailableInProduction(Feature feature) { switch (feature) { #define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option) \ case Feature::FeatureName: return true; -#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \ +#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \ case Feature::FeatureName: return AvailableInProd; #include "swift/Basic/Features.def" } @@ -504,7 +504,7 @@ llvm::Optional swift::getUpcomingFeature(llvm::StringRef name) { llvm::Optional swift::getExperimentalFeature(llvm::StringRef name) { return llvm::StringSwitch>(name) #define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option) -#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \ +#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \ .Case(#FeatureName, Feature::FeatureName) #include "swift/Basic/Features.def" .Default(None); @@ -520,6 +520,17 @@ llvm::Optional swift::getFeatureLanguageVersion(Feature feature) { } } +bool swift::includeInModuleInterface(Feature feature) { + switch (feature) { +#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option) \ + case Feature::FeatureName: return true; +#define EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE(FeatureName, AvailableInProd) \ + case Feature::FeatureName: return false; +#include "swift/Basic/Features.def" + } + llvm_unreachable("covered switch"); +} + DiagnosticBehavior LangOptions::getAccessNoteFailureLimit() const { switch (AccessNoteBehavior) { case AccessNoteDiagnosticBehavior::Ignore: diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index efb36aa088bef..6ddbbee2b0fe2 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -392,6 +392,19 @@ static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts, } } +/// Checks if an arg is generally allowed to be included +/// in a module interface +static bool ShouldIncludeModuleInterfaceArg(const Arg *A) { + if (!A->getOption().matches(options::OPT_enable_experimental_feature)) + return true; + + if (auto feature = getExperimentalFeature(A->getValue())) { + return swift::includeInModuleInterface(*feature); + } + + return true; +} + /// Save a copy of any flags marked as ModuleInterfaceOption, if running /// in a mode that is going to emit a .swiftinterface file. static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts, @@ -402,6 +415,9 @@ static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts, ArgStringList RenderedArgs; ArgStringList RenderedArgsIgnorable; for (auto A : Args) { + if (!ShouldIncludeModuleInterfaceArg(A)) + continue; + if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorable)) { A->render(Args, RenderedArgsIgnorable); } else if (A->getOption().hasFlag(options::ModuleInterfaceOption)) { diff --git a/test/ModuleInterface/option-filtering.swift b/test/ModuleInterface/option-filtering.swift new file mode 100644 index 0000000000000..959d4883ffd7b --- /dev/null +++ b/test/ModuleInterface/option-filtering.swift @@ -0,0 +1,10 @@ +// RUN: %empty-directory(%t) + +// 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 +// RUN: %FileCheck %s < %t.swiftinterface -check-prefix=CHECK-SWIFTINTERFACE +// +// CHECK-SWIFTINTERFACE: swift-module-flags-ignorable: +// CHECK-SWIFTINTERFACE-NOT: -enable-experimental-feature LayoutStringValueWitnesses +// CHECK-SWIFTINTERFACE-NOT: -enable-experimental-feature LayoutStringValueWitnessesInstantiation + +public func foo() { }