Skip to content

Commit 47e32f2

Browse files
committed
Sema: Relax availability checking for @MainActor(unsafe).
The `@MainActor(unsafe)` global actor constraint on a type does not carry an ABI impact and therefore use of this constraint should not be limited to OS versions where Swift concurrency is available. Resolves rdar://105610970
1 parent 8ddbc68 commit 47e32f2

File tree

9 files changed

+72
-36
lines changed

9 files changed

+72
-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
@@ -3937,6 +3937,9 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
39373937
/// Whether this nominal type qualifies as any actor (plain or distributed).
39383938
bool isAnyActor() const;
39393939

3940+
/// Whether this nominal type is the `MainActor` global actor.
3941+
bool isMainActor() const;
3942+
39403943
/// Return the range of semantics attributes attached to this NominalTypeDecl.
39413944
auto getSemanticsAttrs() const
39423945
-> decltype(getAttrs().getSemanticsAttrs()) {

lib/AST/Decl.cpp

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

4844+
bool NominalTypeDecl::isMainActor() const {
4845+
return getName().is("MainActor") &&
4846+
getParentModule()->getName() == getASTContext().Id_Concurrency;
4847+
}
4848+
48444849
GenericTypeDecl::GenericTypeDecl(DeclKind K, DeclContext *DC,
48454850
Identifier name, SourceLoc nameLoc,
48464851
ArrayRef<InheritedEntry> inherited,
@@ -9937,6 +9942,15 @@ void swift::simple_display(llvm::raw_ostream &out, AnyFunctionRef fn) {
99379942
out << "closure";
99389943
}
99399944

9945+
bool ActorIsolation::isMainActor() const {
9946+
if (isGlobalActor()) {
9947+
if (auto *nominal = getGlobalActor()->getAnyNominal())
9948+
return nominal->isMainActor();
9949+
}
9950+
9951+
return false;
9952+
}
9953+
99409954
bool ActorIsolation::isDistributedActor() const {
99419955
return getKind() == ActorInstance && getActor()->isDistributedActor();
99429956
}

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/Sema/TypeCheckAccess.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,13 +1946,24 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
19461946
explicit DeclAvailabilityChecker(ExportContext where)
19471947
: Where(where) {}
19481948

1949+
void checkGlobalActor(Decl *D) {
1950+
auto globalActor = D->getGlobalActorAttr();
1951+
if (!globalActor)
1952+
return;
1953+
1954+
auto customAttr = globalActor->first;
1955+
1956+
// Avoid checking the availability for a @MainActor(unsafe) constraint
1957+
// since it carries no ABI impact.
1958+
if (globalActor->second->isMainActor() && customAttr->isArgUnsafe())
1959+
return;
1960+
1961+
checkType(customAttr->getType(), customAttr->getTypeRepr(), D);
1962+
}
1963+
19491964
void visit(Decl *D) {
19501965
DeclVisitor<DeclAvailabilityChecker>::visit(D);
1951-
1952-
if (auto globalActor = D->getGlobalActorAttr()) {
1953-
auto customAttr = globalActor->first;
1954-
checkType(customAttr->getType(), customAttr->getTypeRepr(), D);
1955-
}
1966+
checkGlobalActor(D);
19561967
}
19571968

19581969
// 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
@@ -3616,15 +3616,6 @@ void AttributeChecker::visitFrozenAttr(FrozenAttr *attr) {
36163616
}
36173617
}
36183618

3619-
/// Determine whether this is the main actor type.
3620-
/// FIXME: the diagnostics engine and TypeCheckConcurrency both have a copy of
3621-
/// this
3622-
static bool isMainActor(NominalTypeDecl *nominal) {
3623-
return nominal->getName().is("MainActor") &&
3624-
nominal->getParentModule()->getName() ==
3625-
nominal->getASTContext().Id_Concurrency;
3626-
}
3627-
36283619
void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
36293620
auto dc = D->getDeclContext();
36303621

@@ -3667,7 +3658,7 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
36673658
return;
36683659
}
36693660

3670-
if (isMainActor(nominal) && Ctx.LangOpts.isConcurrencyModelTaskToThread() &&
3661+
if (nominal->isMainActor() && Ctx.LangOpts.isConcurrencyModelTaskToThread() &&
36713662
!AvailableAttr::isUnavailable(D)) {
36723663
Ctx.Diags.diagnose(attr->getLocation(),
36733664
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
@@ -1226,14 +1226,9 @@ void swift::diagnoseMissingExplicitSendable(NominalTypeDecl *nominal) {
12261226
}
12271227

12281228
/// Determine whether this is the main actor type.
1229-
/// FIXME: the diagnostics engine has a copy of this.
12301229
static bool isMainActor(Type type) {
1231-
if (auto nominal = type->getAnyNominal()) {
1232-
if (nominal->getName().is("MainActor") &&
1233-
nominal->getParentModule()->getName() ==
1234-
nominal->getASTContext().Id_Concurrency)
1235-
return true;
1236-
}
1230+
if (auto nominal = type->getAnyNominal())
1231+
return nominal->isMainActor();
12371232

12381233
return false;
12391234
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// REQUIRES: concurrency
4+
// REQUIRES: vendor=apple
5+
6+
@MainActor // expected-error {{'MainActor' is only available in}}
7+
struct AlwaysAvailable {} // expected-note {{add @available attribute to enclosing struct}}
8+
9+
@MainActor(unsafe)
10+
struct AlwaysAvailableUnsafe {}
11+
12+
@available(SwiftStdlib 5.1, *)
13+
@MainActor
14+
struct AvailableSwift5_1 {}
15+
16+
@available(SwiftStdlib 5.1, *)
17+
@MainActor(unsafe)
18+
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)