Skip to content

Commit 4d620c8

Browse files
committed
Sema: Diagnose when the access level of the global actor for a declaration is inconsistent with the access level of the declaration.
Resolves rdar://98200658 and #60420.
1 parent d5391d0 commit 4d620c8

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4882,6 +4882,11 @@ ERROR(global_actor_non_final_class,none,
48824882
"non-final class %0 cannot be a global actor", (DeclName))
48834883
ERROR(global_actor_top_level_var,none,
48844884
"top-level code variables cannot have a global actor", ())
4885+
ERROR(global_actor_access,none,
4886+
"%select{private|fileprivate|internal|public|open}0 %1 %2 "
4887+
"cannot have %select{private|fileprivate|internal|%error|%error}3 "
4888+
"global actor %4",
4889+
(AccessLevel, DescriptiveDeclKind, DeclName, AccessLevel, DeclName))
48854890

48864891
ERROR(actor_isolation_multiple_attr,none,
48874892
"%0 %1 has multiple actor-isolation attributes ('%2' and '%3')",

lib/Sema/TypeCheckAccess.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ class AccessControlCheckerBase {
108108
void checkGenericParamAccess(
109109
const GenericContext *ownerCtx,
110110
const ValueDecl *ownerDecl);
111+
112+
void checkGlobalActorAccess(const ValueDecl *D);
111113
};
112114

113115
class TypeAccessScopeDiagnoser : private ASTWalker {
@@ -409,6 +411,30 @@ void AccessControlCheckerBase::checkGenericParamAccess(
409411
ownerDecl->getFormalAccess());
410412
}
411413

414+
void AccessControlCheckerBase::checkGlobalActorAccess(const ValueDecl *D) {
415+
auto globalActorAttr = D->getGlobalActorAttr();
416+
if (!globalActorAttr)
417+
return;
418+
419+
auto customAttr = globalActorAttr->first;
420+
auto globalActorDecl = globalActorAttr->second;
421+
checkTypeAccess(
422+
customAttr->getType(), customAttr->getTypeRepr(), D,
423+
/*mayBeInferred*/ false,
424+
[&](AccessScope typeAccessScope, const TypeRepr *complainRepr,
425+
DowngradeToWarning downgradeToWarning) {
426+
auto globalActorAccess = typeAccessScope.accessLevelForDiagnostics();
427+
bool isExplicit = D->getAttrs().hasAttribute<AccessControlAttr>();
428+
auto declAccess = isExplicit
429+
? D->getFormalAccess()
430+
: typeAccessScope.requiredAccessForDiagnostics();
431+
auto diag = D->diagnose(diag::global_actor_access, declAccess,
432+
D->getDescriptiveKind(), D->getName(),
433+
globalActorAccess, globalActorDecl->getName());
434+
highlightOffendingType(diag, complainRepr);
435+
});
436+
}
437+
412438
namespace {
413439
class AccessControlChecker : public AccessControlCheckerBase,
414440
public DeclVisitor<AccessControlChecker> {
@@ -425,6 +451,9 @@ class AccessControlChecker : public AccessControlCheckerBase,
425451
return;
426452

427453
DeclVisitor<AccessControlChecker>::visit(D);
454+
455+
if (const auto *VD = dyn_cast<ValueDecl>(D))
456+
checkGlobalActorAccess(VD);
428457
}
429458

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

test/attr/global_actor.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,38 @@ struct Container {
100100
extension SomeActor {
101101
@GA1 nonisolated func conflict1() { } // expected-error 3{{instance method 'conflict1()' has multiple actor-isolation attributes ('nonisolated' and 'GA1')}}
102102
}
103+
104+
105+
// -----------------------------------------------------------------------
106+
// Access
107+
// -----------------------------------------------------------------------
108+
109+
@globalActor
110+
private struct PrivateGA { // expected-note 2 {{type declared here}}
111+
actor Actor {}
112+
static let shared = Actor()
113+
}
114+
115+
@globalActor
116+
internal struct InternalGA { // expected-note 1 {{type declared here}}
117+
actor Actor {}
118+
static let shared = Actor()
119+
}
120+
121+
@globalActor
122+
public struct PublicGA {
123+
public actor Actor {}
124+
public static let shared = Actor()
125+
}
126+
127+
@PrivateGA private struct PrivateStructPrivateGA {}
128+
@InternalGA private struct PrivateStructInternalGA {}
129+
@PublicGA private struct PrivateStructPublicGA {}
130+
131+
@PrivateGA internal struct InternalStructPrivateGA {} // expected-error {{internal struct 'InternalStructPrivateGA' cannot have private global actor 'PrivateGA'}}
132+
@InternalGA internal struct InternalStructInternalGA {}
133+
@PublicGA internal struct InternalStructPublicGA {}
134+
135+
@PrivateGA open class OpenClassPrivateGA {} // expected-error {{open class 'OpenClassPrivateGA' cannot have private global actor 'PrivateGA'}}
136+
@InternalGA open class OpenClassInternalGA {} // expected-error {{open class 'OpenClassInternalGA' cannot have internal global actor 'InternalGA'}}
137+
@PublicGA open class OpenClassPublicGA {}

0 commit comments

Comments
 (0)