Add an optional language feature for Library Evolution

Replace the one-off compiler flag for Library Evolution with an
optional language feature. This makes the
`hasFeature(LibraryEvolution)` check work in an `#if`, and is
otherwise just cleanup.

Tracked by rdar://161125572.
This commit is contained in:
Doug Gregor
2025-09-22 17:45:34 -07:00
parent 87cbe5d2a9
commit c68ef1cf71
12 changed files with 28 additions and 28 deletions

View File

@@ -308,6 +308,8 @@ UPCOMING_FEATURE(ImmutableWeakCaptures, 481, 7)
/// safety.
MIGRATABLE_OPTIONAL_LANGUAGE_FEATURE(StrictMemorySafety, 458, "Strict memory safety")
OPTIONAL_LANGUAGE_FEATURE(LibraryEvolution, 0, "Library evolution")
// Experimental features
EXPERIMENTAL_FEATURE(StaticAssert, false)

View File

@@ -298,11 +298,6 @@ public:
/// \see ModuleDecl::isImplicitDynamicEnabled
bool EnableImplicitDynamic = false;
/// Enables the "fully resilient" resilience strategy.
///
/// \see ResilienceStrategy::Resilient
bool EnableLibraryEvolution = false;
/// If set, this module is part of a mixed Objective-C/Swift framework, and
/// the Objective-C half should implicitly be visible to the Swift sources.
bool ImportUnderlyingModule = false;

View File

@@ -25,20 +25,16 @@ class SourceLoader : public ModuleLoader {
private:
ASTContext &Ctx;
std::vector<ModuleDecl *> ModulesToBindExtensions;
bool EnableLibraryEvolution;
explicit SourceLoader(ASTContext &ctx,
bool enableResilience,
DependencyTracker *tracker)
: ModuleLoader(tracker), Ctx(ctx),
EnableLibraryEvolution(enableResilience) {}
: ModuleLoader(tracker), Ctx(ctx) {}
public:
static std::unique_ptr<SourceLoader>
create(ASTContext &ctx, bool enableResilience,
DependencyTracker *tracker = nullptr) {
create(ASTContext &ctx, DependencyTracker *tracker = nullptr) {
return std::unique_ptr<SourceLoader>{
new SourceLoader(ctx, enableResilience, tracker)
new SourceLoader(ctx, tracker)
};
}

View File

@@ -327,6 +327,7 @@ static bool usesFeatureCDecl(Decl *decl) {
}
UNINTERESTING_FEATURE(StrictMemorySafety)
UNINTERESTING_FEATURE(LibraryEvolution)
UNINTERESTING_FEATURE(SafeInteropWrappers)
UNINTERESTING_FEATURE(AssumeResilientCxxTypes)
UNINTERESTING_FEATURE(ImportNonPublicCxxMembers)

View File

@@ -59,6 +59,9 @@ static std::optional<std::string_view> optionalFlagName(Feature feature) {
case Feature::StrictMemorySafety:
return "-strict-memory-safety";
case Feature::LibraryEvolution:
return "-enable-library-evolution";
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) case Feature::FeatureName:
#define OPTIONAL_LANGUAGE_FEATURE(FeatureName, SENumber, Description)
#include "swift/Basic/Features.def"

View File

@@ -704,8 +704,8 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
Invocation.setTargetTriple(options.Target);
if (!options.ResourceDir.empty())
Invocation.setRuntimeResourcePath(options.ResourceDir);
Invocation.getFrontendOptions().EnableLibraryEvolution
= options.EnableLibraryEvolution;
if (options.EnableLibraryEvolution)
Invocation.getLangOptions().enableFeature(Feature::LibraryEvolution);
Invocation.getFrontendOptions().StrictImplicitModuleContext
= options.StrictImplicitModuleContext;

View File

@@ -140,7 +140,7 @@ int swift_symbolgraph_extract_main(ArrayRef<const char *> Args,
Invocation.getLangOptions().EnableObjCInterop = Target.isOSDarwin();
Invocation.getLangOptions().DebuggerSupport = true;
Invocation.getFrontendOptions().EnableLibraryEvolution = true;
Invocation.getLangOptions().enableFeature(Feature::LibraryEvolution);
std::string ModuleCachePath = "";
if (auto *A = ParsedArgs.getLastArg(OPT_module_cache_path)) {

View File

@@ -107,16 +107,12 @@ bool ArgsToFrontendOptionsConverter::convert(
Opts.EnableTesting |= Args.hasArg(OPT_enable_testing);
Opts.EnablePrivateImports |= Args.hasArg(OPT_enable_private_imports);
Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_library_evolution);
Opts.FrontendParseableOutput |= Args.hasArg(OPT_frontend_parseable_output);
Opts.ExplicitInterfaceBuild |= Args.hasArg(OPT_explicit_interface_module_build);
Opts.EmitClangHeaderWithNonModularIncludes |=
Args.hasArg(OPT_emit_clang_header_nonmodular_includes);
// FIXME: Remove this flag
Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_resilience);
Opts.EnableImplicitDynamic |= Args.hasArg(OPT_enable_implicit_dynamic);
if (Args.hasArg(OPT_track_system_dependencies)) {

View File

@@ -1011,6 +1011,9 @@ static bool ParseEnabledFeatureArgs(LangOptions &Opts, ArgList &Args,
else if (Args.hasArg(OPT_strict_memory_safety_migrate))
Opts.enableFeature(Feature::StrictMemorySafety, /*forMigration=*/true);
if (Args.hasArg(OPT_enable_library_evolution, OPT_enable_resilience))
Opts.enableFeature(Feature::LibraryEvolution);
return HadError;
}
@@ -1799,7 +1802,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
HadError = true;
}
if (FrontendOpts.EnableLibraryEvolution) {
if (Opts.hasFeature(Feature::LibraryEvolution)) {
Diags.diagnose(SourceLoc(), diag::evolution_with_embedded);
HadError = true;
}
@@ -2131,7 +2134,8 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, ArgList &Args,
// Until we have some checking in place, internal bridging headers are a
// bit unsafe without library evolution.
if (Opts.BridgingHeaderIsInternal && !FrontendOpts.EnableLibraryEvolution) {
if (Opts.BridgingHeaderIsInternal &&
!LangOpts.hasFeature(Feature::LibraryEvolution)) {
Diags.diagnose(SourceLoc(),
diag::internal_bridging_header_without_library_evolution);
}
@@ -3068,7 +3072,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
FrontendOptions::ActionType::TypecheckModuleFromInterface)
Diags.diagnose(SourceLoc(), diag::ignoring_option_requires_option,
"-package-cmo", "-allow-non-resilient-access");
} else if (!FEOpts.EnableLibraryEvolution) {
} else if (!LangOpts.hasFeature(Feature::LibraryEvolution)) {
Diags.diagnose(SourceLoc(), diag::package_cmo_requires_library_evolution);
} else {
Opts.EnableSerializePackage = true;

View File

@@ -813,10 +813,7 @@ bool CompilerInstance::setUpModuleLoaders() {
}
if (hasSourceImport()) {
bool enableLibraryEvolution =
Invocation.getFrontendOptions().EnableLibraryEvolution;
Context->addModuleLoader(SourceLoader::create(*Context,
enableLibraryEvolution,
getDependencyTracker()));
}
@@ -1173,7 +1170,7 @@ bool CompilerInvocation::shouldImportCxx() const {
if (getFrontendOptions().ModuleName == CXX_MODULE_NAME)
return false;
// Cxx cannot be imported when Library evolution is enabled
if (getFrontendOptions().EnableLibraryEvolution)
if (getLangOptions().hasFeature(Feature::LibraryEvolution))
return false;
// Implicit import of Cxx is disabled
if (getLangOptions().DisableImplicitCxxModuleImport)
@@ -1507,7 +1504,7 @@ ModuleDecl *CompilerInstance::getMainModule() const {
MainModule->setPublicModuleName(getASTContext().getIdentifier(
Invocation.getFrontendOptions().PublicModuleName));
}
if (Invocation.getFrontendOptions().EnableLibraryEvolution)
if (Invocation.getLangOptions().hasFeature(Feature::LibraryEvolution))
MainModule->setResilienceStrategy(ResilienceStrategy::Resilient);
if (Invocation.getLangOptions().isSwiftVersionAtLeast(6))
MainModule->setIsConcurrencyChecked(true);

View File

@@ -139,7 +139,7 @@ ModuleDecl *SourceLoader::loadModule(SourceLoc importLoc,
addFile(new (Ctx) SourceFile(*importMod, SourceFileKind::Library, bufferID,
opts));
});
if (EnableLibraryEvolution)
if (Ctx.LangOpts.hasFeature(Feature::LibraryEvolution))
importMod->setResilienceStrategy(ResilienceStrategy::Resilient);
Ctx.addLoadedModule(importMod);
Ctx.bumpGeneration();

View File

@@ -0,0 +1,6 @@
// RUN: %target-typecheck-verify-swift -enable-library-evolution
#if hasFeature(LibraryEvolution)
#else
#error("Missing feature")
#endif