Skip to content

Commit 7db51a5

Browse files
authored
Merge pull request #64538 from tshortli/relax-unsafe-main-actor-availability-checking-5.8
[5.8] Sema: Relax availability checking for `@MainActor`
2 parents 46cd560 + 48cb50e commit 7db51a5

File tree

10 files changed

+78
-36
lines changed

10 files changed

+78
-36
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ class ActorIsolation {
160160
return getKind() == GlobalActor || getKind() == GlobalActorUnsafe;
161161
}
162162

163+
bool isMainActor() const;
164+
163165
bool isDistributedActor() const;
164166

165167
Type getGlobalActor() const {

include/swift/AST/Decl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3834,6 +3834,9 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
38343834
/// Whether this nominal type qualifies as any actor (plain or distributed).
38353835
bool isAnyActor() const;
38363836

3837+
/// Whether this nominal type is the `MainActor` global actor.
3838+
bool isMainActor() const;
3839+
38373840
/// Return the range of semantics attributes attached to this NominalTypeDecl.
38383841
auto getSemanticsAttrs() const
38393842
-> decltype(getAttrs().getSemanticsAttrs()) {

lib/AST/Decl.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4567,6 +4567,11 @@ bool NominalTypeDecl::isAnyActor() const {
45674567
return isActor() || isDistributedActor();
45684568
}
45694569

4570+
bool NominalTypeDecl::isMainActor() const {
4571+
return getName().is("MainActor") &&
4572+
getParentModule()->getName() == getASTContext().Id_Concurrency;
4573+
}
4574+
45704575
GenericTypeDecl::GenericTypeDecl(DeclKind K, DeclContext *DC,
45714576
Identifier name, SourceLoc nameLoc,
45724577
ArrayRef<InheritedEntry> inherited,
@@ -9614,6 +9619,15 @@ void swift::simple_display(llvm::raw_ostream &out, AnyFunctionRef fn) {
96149619
out << "closure";
96159620
}
96169621

9622+
bool ActorIsolation::isMainActor() const {
9623+
if (isGlobalActor()) {
9624+
if (auto *nominal = getGlobalActor()->getAnyNominal())
9625+
return nominal->isMainActor();
9626+
}
9627+
9628+
return false;
9629+
}
9630+
96179631
bool ActorIsolation::isDistributedActor() const {
96189632
return getKind() == ActorInstance && getActor()->isDistributedActor();
96199633
}

lib/AST/DiagnosticEngine.cpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -576,18 +576,6 @@ static bool typeSpellingIsAmbiguous(Type type,
576576
return false;
577577
}
578578

579-
/// Determine whether this is the main actor type.
580-
static bool isMainActor(Type type) {
581-
if (auto nominal = type->getAnyNominal()) {
582-
if (nominal->getName().is("MainActor") &&
583-
nominal->getParentModule()->getName() ==
584-
nominal->getASTContext().Id_Concurrency)
585-
return true;
586-
}
587-
588-
return false;
589-
}
590-
591579
void swift::printClangDeclName(const clang::NamedDecl *ND,
592580
llvm::raw_ostream &os) {
593581
ND->getNameForDiagnostic(os, ND->getASTContext().getPrintingPolicy(), false);
@@ -841,10 +829,10 @@ static void formatDiagnosticArgument(StringRef Modifier,
841829

842830
case ActorIsolation::GlobalActor:
843831
case ActorIsolation::GlobalActorUnsafe: {
844-
Type globalActor = isolation.getGlobalActor();
845-
if (isMainActor(globalActor)) {
832+
if (isolation.isMainActor()) {
846833
Out << "main actor-isolated";
847834
} else {
835+
Type globalActor = isolation.getGlobalActor();
848836
Out << "global actor " << FormatOpts.OpeningQuotationMark
849837
<< globalActor.getString()
850838
<< FormatOpts.ClosingQuotationMark << "-isolated";

lib/SILGen/SILGenProlog.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,11 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo,
712712
!isInActorDestructor(FunctionDC) &&
713713
!F.isDefer();
714714

715+
// FIXME: Avoid loading and checking the expected executor if concurrency is
716+
// unavailable. This is specifically relevant for MainActor isolated contexts,
717+
// which are allowed to be available on OSes where concurrency is not
718+
// available. rdar://106827064
719+
715720
// Local function to load the expected executor from a local actor
716721
auto loadExpectedExecutorForLocalVar = [&](VarDecl *var) {
717722
auto loc = RegularLocation::getAutoGeneratedLocation(F.getLocation());

lib/Sema/TypeCheckAccess.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,13 +1744,23 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
17441744
explicit DeclAvailabilityChecker(ExportContext where)
17451745
: Where(where) {}
17461746

1747+
void checkGlobalActor(Decl *D) {
1748+
auto globalActor = D->getGlobalActorAttr();
1749+
if (!globalActor)
1750+
return;
1751+
1752+
// Avoid checking the availability for a @MainActor constraint since it does
1753+
// not carry an inherent ABI impact.
1754+
if (globalActor->second->isMainActor())
1755+
return;
1756+
1757+
auto customAttr = globalActor->first;
1758+
checkType(customAttr->getType(), customAttr->getTypeRepr(), D);
1759+
}
1760+
17471761
void visit(Decl *D) {
17481762
DeclVisitor<DeclAvailabilityChecker>::visit(D);
1749-
1750-
if (auto globalActor = D->getGlobalActorAttr()) {
1751-
auto customAttr = globalActor->first;
1752-
checkType(customAttr->getType(), customAttr->getTypeRepr(), D);
1753-
}
1763+
checkGlobalActor(D);
17541764
}
17551765

17561766
// Force all kinds to be handled at a lower level.

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3538,15 +3538,6 @@ void AttributeChecker::visitFrozenAttr(FrozenAttr *attr) {
35383538
}
35393539
}
35403540

3541-
/// Determine whether this is the main actor type.
3542-
/// FIXME: the diagnostics engine and TypeCheckConcurrency both have a copy of
3543-
/// this
3544-
static bool isMainActor(NominalTypeDecl *nominal) {
3545-
return nominal->getName().is("MainActor") &&
3546-
nominal->getParentModule()->getName() ==
3547-
nominal->getASTContext().Id_Concurrency;
3548-
}
3549-
35503541
void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
35513542
auto dc = D->getDeclContext();
35523543

@@ -3582,7 +3573,7 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
35823573
return;
35833574
}
35843575

3585-
if (isMainActor(nominal) && Ctx.LangOpts.isConcurrencyModelTaskToThread() &&
3576+
if (nominal->isMainActor() && Ctx.LangOpts.isConcurrencyModelTaskToThread() &&
35863577
!AvailableAttr::isUnavailable(D)) {
35873578
Ctx.Diags.diagnose(attr->getLocation(),
35883579
diag::concurrency_task_to_thread_model_main_actor,

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,14 +1193,9 @@ void swift::diagnoseMissingExplicitSendable(NominalTypeDecl *nominal) {
11931193
}
11941194

11951195
/// Determine whether this is the main actor type.
1196-
/// FIXME: the diagnostics engine has a copy of this.
11971196
static bool isMainActor(Type type) {
1198-
if (auto nominal = type->getAnyNominal()) {
1199-
if (nominal->getName().is("MainActor") &&
1200-
nominal->getParentModule()->getName() ==
1201-
nominal->getASTContext().Id_Concurrency)
1202-
return true;
1203-
}
1197+
if (auto nominal = type->getAnyNominal())
1198+
return nominal->isMainActor();
12041199

12051200
return false;
12061201
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// REQUIRES: concurrency
4+
5+
// This test is meant to verify that a @MainActor constraint is accepted without
6+
// any availability restrictions for all targets.
7+
8+
@MainActor
9+
struct AlwaysAvailable {}
10+
11+
@MainActor(unsafe)
12+
struct AlwaysAvailableUnsafe {}
13+
14+
@available(SwiftStdlib 5.1, *)
15+
@MainActor
16+
struct AvailableSwift5_1 {}
17+
18+
@available(SwiftStdlib 5.1, *)
19+
@MainActor(unsafe)
20+
struct AvailableSwift5_1Unsafe {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-emit-module-interface(%t/Library.swiftinterface) %s -module-name Library
3+
// RUN: %target-swift-typecheck-module-from-interface(%t/Library.swiftinterface) -module-name Library
4+
// RUN: %FileCheck %s < %t/Library.swiftinterface
5+
6+
// REQUIRES: OS=macosx
7+
8+
import AppKit
9+
10+
// CHECK: @objc @_inheritsConvenienceInitializers @_Concurrency.MainActor(unsafe) public class Subclass : AppKit.NSView {
11+
public class Subclass: NSView {
12+
// CHECK: @_Concurrency.MainActor(unsafe) @objc override dynamic public init(frame frameRect: Foundation.NSRect)
13+
// CHECK: @_Concurrency.MainActor(unsafe) @objc required dynamic public init?(coder: Foundation.NSCoder)
14+
}

0 commit comments

Comments
 (0)