Skip to content

Commit 7e3921c

Browse files
committed
[Concurrency] Simplify the logic in computeDefaultInferredActorIsolation.
1 parent 5ef33db commit 7e3921c

File tree

3 files changed

+36
-53
lines changed

3 files changed

+36
-53
lines changed

include/swift/AST/SourceFile.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/Import.h"
2121
#include "swift/AST/SynthesizedFileUnit.h"
2222
#include "swift/Basic/Debug.h"
23+
#include "swift/Basic/LangOptions.h"
2324
#include "llvm/ADT/Hashing.h"
2425
#include "llvm/ADT/STLExtras.h"
2526
#include "llvm/ADT/SetVector.h"
@@ -58,9 +59,9 @@ using ImportAccessLevel = std::optional<AttributedImport<ImportedModule>>;
5859
///
5960
/// Vended by SourceFile::getLanguageOptions().
6061
struct SourceFileLangOptions {
61-
/// If unset, no value was provided. If a Type, that type is the type of the
62-
/// isolation. If set to an empty type, nil was specified explicitly.
63-
std::optional<Type> defaultIsolation;
62+
/// The default actor isolation to infer on declarations
63+
/// within the source file.
64+
std::optional<DefaultIsolation> defaultIsolation;
6465
};
6566

6667
/// A file containing Swift source code.

lib/AST/Module.cpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4223,12 +4223,11 @@ struct SwiftSettingsWalker : ASTWalker {
42234223
}
42244224

42254225
/// Given a specific CallExpr, pattern matches the CallExpr's first argument
4226-
/// to validate it is MainActor.self. Returns CanType() if the CallExpr has
4227-
/// multiple parameters or if its first parameter is not a MainActor.self.
4226+
/// to validate it is MainActor.self.
42284227
///
4229-
/// This is used when pattern matching against
4230-
/// .defaultIsolation(MainActor.self).
4231-
CanType patternMatchDefaultIsolationMainActor(CallExpr *callExpr);
4228+
/// \returns \c true if the call has one argument that matches
4229+
/// \c MainActor.self, and \c false otherwise.
4230+
bool patternMatchDefaultIsolationMainActor(CallExpr *callExpr);
42324231

42334232
/// Validates that macroExpr is a well formed "SwiftSettings" macro. Returns
42344233
/// true if we can process it and false otherwise.
@@ -4294,16 +4293,16 @@ struct SwiftSettingsWalker : ASTWalker {
42944293
}
42954294

42964295
// Otherwise, set things up appropriately.
4297-
if (auto actor = patternMatchDefaultIsolationMainActor(callExpr)) {
4296+
if (patternMatchDefaultIsolationMainActor(callExpr)) {
42984297
expr = callExpr;
4299-
result.defaultIsolation = actor;
4298+
result.defaultIsolation = DefaultIsolation::MainActor;
43004299
foundValidArg = true;
43014300
continue;
43024301
}
43034302

43044303
if (isa<NilLiteralExpr>(callExpr->getArgs()->getExpr(0))) {
43054304
expr = callExpr;
4306-
result.defaultIsolation = {Type()};
4305+
result.defaultIsolation = DefaultIsolation::Nonisolated;
43074306
foundValidArg = true;
43084307
continue;
43094308
}
@@ -4405,18 +4404,18 @@ SwiftSettingsWalker::getSwiftSettingArgDecl(Argument arg) {
44054404
return {{callExpr, f}};
44064405
}
44074406

4408-
CanType
4407+
bool
44094408
SwiftSettingsWalker::patternMatchDefaultIsolationMainActor(CallExpr *callExpr) {
44104409
// Grab the dot self expr.
44114410
auto *selfExpr = dyn_cast<DotSelfExpr>(callExpr->getArgs()->getExpr(0));
44124411
if (!selfExpr)
4413-
return CanType();
4412+
return false;
44144413

44154414
// Then validate we have something that is MainActor.
44164415
auto *declRefExpr = dyn_cast<UnresolvedDeclRefExpr>(selfExpr->getSubExpr());
44174416
if (!declRefExpr ||
44184417
!declRefExpr->getName().getBaseName().getIdentifier().is("MainActor"))
4419-
return CanType();
4418+
return false;
44204419

44214420
// Then use unqualified lookup descriptor to find our MainActor.
44224421
UnqualifiedLookupDescriptor lookupDesc{
@@ -4425,20 +4424,20 @@ SwiftSettingsWalker::patternMatchDefaultIsolationMainActor(CallExpr *callExpr) {
44254424
auto lookup = evaluateOrDefault(ctx.evaluator,
44264425
UnqualifiedLookupRequest{lookupDesc}, {});
44274426
if (lookup.allResults().empty())
4428-
return CanType();
4427+
return false;
44294428

44304429
// Then grab our nominal type decl and make sure it is from the concurrency
44314430
// module.
44324431
auto *nomDecl =
44334432
dyn_cast<NominalTypeDecl>(lookup.allResults().front().getValueDecl());
44344433
if (!nomDecl)
4435-
return CanType();
4434+
return false;
44364435
auto *nomDeclDC = nomDecl->getDeclContext();
44374436
auto *nomDeclModule = nomDecl->getParentModule();
44384437
if (!nomDeclDC->isModuleScopeContext() || !nomDeclModule->isConcurrencyModule())
4439-
return CanType();
4438+
return false;
44404439

4441-
return nomDecl->getDeclaredType()->getCanonicalType();
4440+
return true;
44424441
}
44434442

44444443
SourceFileLangOptions

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5739,12 +5739,21 @@ static std::tuple<InferredActorIsolation, ValueDecl *,
57395739
computeDefaultInferredActorIsolation(ValueDecl *value) {
57405740
auto &ctx = value->getASTContext();
57415741

5742-
// If we are supposed to infer main actor isolation by default for entities
5743-
// within our module, make our default isolation main actor.
5742+
// Determine whether default isolation is set to MainActor, either for
5743+
// the entire module or in this specific file.
57445744
if (value->getModuleContext() == ctx.MainModule) {
5745-
auto globalActorHelper = [&](Type globalActor)
5746-
-> std::optional<std::tuple<InferredActorIsolation, ValueDecl *,
5747-
std::optional<ActorIsolation>>> {
5745+
// See if we have one specified by our file unit.
5746+
auto defaultIsolation = ctx.LangOpts.DefaultIsolationBehavior;
5747+
if (ctx.LangOpts.hasFeature(Feature::SwiftSettings)) {
5748+
if (auto *sourceFile = value->getDeclContext()->getParentSourceFile()) {
5749+
auto options = sourceFile->getLanguageOptions();
5750+
if (auto isolation = options.defaultIsolation) {
5751+
defaultIsolation = *isolation;
5752+
}
5753+
}
5754+
}
5755+
5756+
if (defaultIsolation == DefaultIsolation::MainActor) {
57485757
// Default global actor isolation does not apply to any declarations
57495758
// within actors and distributed actors.
57505759
bool inActorContext = false;
@@ -5756,44 +5765,18 @@ computeDefaultInferredActorIsolation(ValueDecl *value) {
57565765
dc = dc->getParent();
57575766
}
57585767

5768+
auto mainActorType = ctx.getMainActorType()->mapTypeOutOfContext();
57595769
if (!inActorContext) {
57605770
// FIXME: deinit should be implicitly MainActor too.
57615771
if (isa<TypeDecl>(value) || isa<ExtensionDecl>(value) ||
57625772
isa<AbstractStorageDecl>(value) || isa<FuncDecl>(value) ||
57635773
isa<ConstructorDecl>(value)) {
5764-
return {
5765-
{{ActorIsolation::forGlobalActor(globalActor), {}}, nullptr, {}}};
5766-
}
5767-
}
5768-
5769-
return {};
5770-
};
5771-
5772-
// Otherwise, see if we have one specified by our file unit.
5773-
bool ignoreUnspecifiedMeansMainActorIsolated = false;
5774-
if (ctx.LangOpts.hasFeature(Feature::SwiftSettings)) {
5775-
if (auto *sourceFile = value->getDeclContext()->getParentSourceFile()) {
5776-
auto options = sourceFile->getLanguageOptions();
5777-
if (auto isolation = options.defaultIsolation) {
5778-
if (*isolation) {
5779-
auto result = globalActorHelper(*options.defaultIsolation);
5780-
if (result)
5781-
return *result;
5782-
} else {
5783-
// If we found a nil type, then we know we should ignore unspecified
5784-
// means main actor isolated.
5785-
ignoreUnspecifiedMeansMainActorIsolated = true;
5786-
}
5774+
auto mainActorIsolation =
5775+
ActorIsolation::forGlobalActor(mainActorType);
5776+
return {{mainActorIsolation, {}}, nullptr, {}};
57875777
}
57885778
}
57895779
}
5790-
5791-
// If we are required to use main actor... just use that.
5792-
if (!ignoreUnspecifiedMeansMainActorIsolated &&
5793-
ctx.LangOpts.DefaultIsolationBehavior == DefaultIsolation::MainActor)
5794-
if (auto result =
5795-
globalActorHelper(ctx.getMainActorType()->mapTypeOutOfContext()))
5796-
return *result;
57975780
}
57985781

57995782
// If we have an async function... by default we inherit isolation.

0 commit comments

Comments
 (0)