[Concurrency] Remove -executor-factory option and replace with magic type.

We decided that using a magic typealias to set the executor factory was better
than using a compiler option. Remove the `-executor-factory` option, and replace
by looking up the `DefaultExecutorFactory` type, first in the main module, and
then if that fails in Concurrency.

rdar://149058236
This commit is contained in:
Alastair Houghton
2025-04-11 12:53:43 +01:00
parent bfe3fe7360
commit 670be7df63
9 changed files with 47 additions and 87 deletions

View File

@@ -1136,12 +1136,9 @@ NOTE(rbi_add_generic_parameter_sendable_conformance,none,
// Concurrency related diagnostics // Concurrency related diagnostics
ERROR(cannot_find_executor_factory_type, none, ERROR(cannot_find_executor_factory_type, none,
"the specified executor factory '%0' could not be found", (StringRef)) "the DefaultExecutorFactory type could not be found", ())
ERROR(executor_factory_must_conform, none, ERROR(executor_factory_must_conform, none,
"the executor factory '%0' does not conform to 'ExecutorFactory'", "the DefaultExecutorFactory does not conform to 'ExecutorFactory'", ())
(StringRef))
ERROR(executor_factory_not_supported, none,
"deployment target too low for executor factory specification", ())
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// MARK: Misc Diagnostics // MARK: Misc Diagnostics

View File

@@ -409,10 +409,6 @@ namespace swift {
/// Specifies how strict concurrency checking will be. /// Specifies how strict concurrency checking will be.
StrictConcurrency StrictConcurrencyLevel = StrictConcurrency::Minimal; StrictConcurrency StrictConcurrencyLevel = StrictConcurrency::Minimal;
/// Specifies the name of the executor factory to use to create the
/// default executors for Swift Concurrency.
std::optional<std::string> ExecutorFactory;
/// Enable experimental concurrency model. /// Enable experimental concurrency model.
bool EnableExperimentalConcurrency = false; bool EnableExperimentalConcurrency = false;

View File

@@ -998,16 +998,6 @@ def default_isolation_EQ : Joined<["-"], "default-isolation=">,
Flags<[FrontendOption]>, Flags<[FrontendOption]>,
Alias<default_isolation>; Alias<default_isolation>;
def executor_factory : JoinedOrSeparate<["-"], "executor-factory">,
Flags<[FrontendOption]>,
HelpText<"Specify the factory to use to create the default executors for "
"Swift Concurrency. This must be a type conforming to the "
"'ExecutorFactory' protocol.">,
MetaVarName<"<factory-type>">;
def executor_factory_EQ : Joined<["-"], "executor-factory=">,
Flags<[FrontendOption]>,
Alias<executor_factory>;
def enable_experimental_feature : def enable_experimental_feature :
Separate<["-"], "enable-experimental-feature">, Separate<["-"], "enable-experimental-feature">,
Flags<[FrontendOption, ModuleInterfaceOption]>, Flags<[FrontendOption, ModuleInterfaceOption]>,

View File

@@ -379,10 +379,6 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
arguments.push_back(inputArgs.MakeArgString(globalRemapping)); arguments.push_back(inputArgs.MakeArgString(globalRemapping));
} }
if (inputArgs.hasArg(options::OPT_executor_factory)) {
inputArgs.AddLastArg(arguments, options::OPT_executor_factory);
}
// Pass through the values passed to -Xfrontend. // Pass through the values passed to -Xfrontend.
inputArgs.AddAllArgValues(arguments, options::OPT_Xfrontend); inputArgs.AddAllArgValues(arguments, options::OPT_Xfrontend);

View File

@@ -1364,12 +1364,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.enableFeature(Feature::RegionBasedIsolation); Opts.enableFeature(Feature::RegionBasedIsolation);
} }
// Get the executor factory name
if (const Arg *A = Args.getLastArg(OPT_executor_factory)) {
printf("Got executor-factory option\n");
Opts.ExecutorFactory = A->getValue();
}
Opts.WarnImplicitOverrides = Opts.WarnImplicitOverrides =
Args.hasArg(OPT_warn_implicit_overrides); Args.hasArg(OPT_warn_implicit_overrides);

View File

@@ -514,25 +514,14 @@ FuncDecl *SILGenModule::getExit() {
Type SILGenModule::getConfiguredExecutorFactory() { Type SILGenModule::getConfiguredExecutorFactory() {
auto &ctx = getASTContext(); auto &ctx = getASTContext();
ModuleDecl *module; // Look in the main module for a typealias
Type factory = ctx.getNamedSwiftType(ctx.MainModule, "DefaultExecutorFactory");
// Parse the executor factory name // If we don't find it, fall back to _Concurrency.PlatformExecutorFactory
StringRef qualifiedName = *ctx.LangOpts.ExecutorFactory; if (!factory)
StringRef typeName; factory = getDefaultExecutorFactory();
auto parts = qualifiedName.split('.'); return factory;
if (parts.second.empty()) {
// This was an unqualified name; assume it's relative to the main module
module = ctx.MainModule;
typeName = qualifiedName;
} else {
Identifier moduleName = ctx.getIdentifier(parts.first);
module = ctx.getModuleByIdentifier(moduleName);
typeName = parts.second;
}
return ctx.getNamedSwiftType(module, typeName);
} }
Type SILGenModule::getDefaultExecutorFactory() { Type SILGenModule::getDefaultExecutorFactory() {

View File

@@ -1424,51 +1424,44 @@ void SILGenFunction::emitAsyncMainThreadStart(SILDeclRef entryPoint) {
B.setInsertionPoint(entryBlock); B.setInsertionPoint(entryBlock);
// If we're using a new enough deployment target, call swift_createExecutors() // If we're using a new enough deployment target, and we can find a
if (ctx.LangOpts.ExecutorFactory) { // DefaultExecutorFactory type, call swift_createExecutors()
if (!isCreateExecutorsFunctionAvailable(SGM)) { Type factoryNonCanTy = SGM.getConfiguredExecutorFactory();
ctx.Diags.diagnose(SourceLoc(), diag::executor_factory_not_supported);
} else {
CanType factoryTy = SGM.getConfiguredExecutorFactory()->getCanonicalType();
if (!factoryTy) { if (isCreateExecutorsFunctionAvailable(SGM) && factoryNonCanTy) {
ctx.Diags.diagnose(SourceLoc(), diag::cannot_find_executor_factory_type, CanType factoryTy = factoryNonCanTy->getCanonicalType();
*ctx.LangOpts.ExecutorFactory);
}
ProtocolDecl *executorFactoryProtocol ProtocolDecl *executorFactoryProtocol
= ctx.getProtocol(KnownProtocolKind::ExecutorFactory); = ctx.getProtocol(KnownProtocolKind::ExecutorFactory);
auto conformance = lookupConformance(factoryTy, executorFactoryProtocol); auto conformance = lookupConformance(factoryTy, executorFactoryProtocol);
if (conformance.isInvalid()) { if (conformance.isInvalid()) {
// If this type doesn't conform, ignore it and use the default factory // If this type doesn't conform, ignore it and use the default factory
SourceLoc loc = extractNearestSourceLoc(factoryTy); SourceLoc loc = extractNearestSourceLoc(factoryTy);
ctx.Diags.diagnose(loc, diag::executor_factory_must_conform, ctx.Diags.diagnose(loc, diag::executor_factory_must_conform);
*ctx.LangOpts.ExecutorFactory);
factoryTy = SGM.getDefaultExecutorFactory()->getCanonicalType(); factoryTy = SGM.getDefaultExecutorFactory()->getCanonicalType();
conformance = lookupConformance(factoryTy, executorFactoryProtocol); conformance = lookupConformance(factoryTy, executorFactoryProtocol);
assert(!conformance.isInvalid()); assert(!conformance.isInvalid());
}
FuncDecl *createExecutorsFuncDecl = SGM.getCreateExecutors();
assert(createExecutorsFuncDecl
&& "Failed to find swift_createExecutors function decl");
SILFunction *createExecutorsSILFunc =
SGM.getFunction(SILDeclRef(createExecutorsFuncDecl, SILDeclRef::Kind::Func),
NotForDefinition);
SILValue createExecutorsFunc =
B.createFunctionRefFor(moduleLoc, createExecutorsSILFunc);
MetatypeType *factoryThickMetaTy
= MetatypeType::get(factoryTy, MetatypeRepresentation::Thick);
SILValue factorySILMetaTy
= B.createMetatype(moduleLoc, getLoweredType(factoryThickMetaTy));
auto ceSubs = SubstitutionMap::getProtocolSubstitutions(
conformance.getProtocol(), factoryTy, conformance);
B.createApply(moduleLoc, createExecutorsFunc, ceSubs, { factorySILMetaTy });
} }
FuncDecl *createExecutorsFuncDecl = SGM.getCreateExecutors();
assert(createExecutorsFuncDecl
&& "Failed to find swift_createExecutors function decl");
SILFunction *createExecutorsSILFunc =
SGM.getFunction(SILDeclRef(createExecutorsFuncDecl, SILDeclRef::Kind::Func),
NotForDefinition);
SILValue createExecutorsFunc =
B.createFunctionRefFor(moduleLoc, createExecutorsSILFunc);
MetatypeType *factoryThickMetaTy
= MetatypeType::get(factoryTy, MetatypeRepresentation::Thick);
SILValue factorySILMetaTy
= B.createMetatype(moduleLoc, getLoweredType(factoryThickMetaTy));
auto ceSubs = SubstitutionMap::getProtocolSubstitutions(
conformance.getProtocol(), factoryTy, conformance);
B.createApply(moduleLoc, createExecutorsFunc, ceSubs, { factorySILMetaTy });
} }
auto wrapCallArgs = [this, &moduleLoc](SILValue originalValue, FuncDecl *fd, auto wrapCallArgs = [this, &moduleLoc](SILValue originalValue, FuncDecl *fd,

View File

@@ -534,6 +534,9 @@ public protocol ExecutorFactory {
static var defaultExecutor: any TaskExecutor { get } static var defaultExecutor: any TaskExecutor { get }
} }
@available(SwiftStdlib 6.2, *)
typealias DefaultExecutorFactory = PlatformExecutorFactory
@available(SwiftStdlib 6.2, *) @available(SwiftStdlib 6.2, *)
@_silgen_name("swift_createExecutors") @_silgen_name("swift_createExecutors")
public func _createExecutors<F: ExecutorFactory>(factory: F.Type) { public func _createExecutors<F: ExecutorFactory>(factory: F.Type) {
@@ -556,7 +559,7 @@ extension MainActor {
@available(SwiftStdlib 6.2, *) @available(SwiftStdlib 6.2, *)
public static var executor: any MainExecutor { public static var executor: any MainExecutor {
if _executor == nil { if _executor == nil {
_executor = PlatformExecutorFactory.mainExecutor _executor = DefaultExecutorFactory.mainExecutor
} }
return _executor! return _executor!
} }
@@ -575,7 +578,7 @@ extension Task where Success == Never, Failure == Never {
@available(SwiftStdlib 6.2, *) @available(SwiftStdlib 6.2, *)
public static var defaultExecutor: any TaskExecutor { public static var defaultExecutor: any TaskExecutor {
if _defaultExecutor == nil { if _defaultExecutor == nil {
_defaultExecutor = PlatformExecutorFactory.defaultExecutor _defaultExecutor = DefaultExecutorFactory.defaultExecutor
} }
return _defaultExecutor! return _defaultExecutor!
} }

View File

@@ -1,4 +1,4 @@
// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking -g %import-libdispatch -parse-as-library -executor-factory SimpleExecutorFactory) | %FileCheck %s // RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking -g %import-libdispatch -parse-as-library) | %FileCheck %s
// REQUIRES: concurrency // REQUIRES: concurrency
// REQUIRES: executable_test // REQUIRES: executable_test
@@ -13,6 +13,8 @@
import StdlibUnittest import StdlibUnittest
import Synchronization import Synchronization
typealias DefaultExecutorFactory = SimpleExecutorFactory
struct SimpleExecutorFactory: ExecutorFactory { struct SimpleExecutorFactory: ExecutorFactory {
public static var mainExecutor: any MainExecutor { public static var mainExecutor: any MainExecutor {
print("Creating main executor") print("Creating main executor")