Skip to content

Commit 0e90e6a

Browse files
committed
Sema: Diagnose use of global actor types with insufficient access on @usableFromInline declarations.
1 parent 4d620c8 commit 0e90e6a

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4887,6 +4887,9 @@ ERROR(global_actor_access,none,
48874887
"cannot have %select{private|fileprivate|internal|%error|%error}3 "
48884888
"global actor %4",
48894889
(AccessLevel, DescriptiveDeclKind, DeclName, AccessLevel, DeclName))
4890+
ERROR(global_actor_not_usable_from_inline,none,
4891+
"global actor for %0 %1 must be '@usableFromInline' or public",
4892+
(DescriptiveDeclKind, DeclName))
48904893

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

lib/Sema/TypeCheckAccess.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class AccessControlCheckerBase {
109109
const GenericContext *ownerCtx,
110110
const ValueDecl *ownerDecl);
111111

112-
void checkGlobalActorAccess(const ValueDecl *D);
112+
void checkGlobalActorAccess(const Decl *D);
113113
};
114114

115115
class TypeAccessScopeDiagnoser : private ASTWalker {
@@ -411,25 +411,36 @@ void AccessControlCheckerBase::checkGenericParamAccess(
411411
ownerDecl->getFormalAccess());
412412
}
413413

414-
void AccessControlCheckerBase::checkGlobalActorAccess(const ValueDecl *D) {
414+
void AccessControlCheckerBase::checkGlobalActorAccess(const Decl *D) {
415+
auto VD = dyn_cast<ValueDecl>(D);
416+
if (!VD)
417+
return;
418+
415419
auto globalActorAttr = D->getGlobalActorAttr();
416420
if (!globalActorAttr)
417421
return;
418422

419423
auto customAttr = globalActorAttr->first;
420424
auto globalActorDecl = globalActorAttr->second;
421425
checkTypeAccess(
422-
customAttr->getType(), customAttr->getTypeRepr(), D,
426+
customAttr->getType(), customAttr->getTypeRepr(), VD,
423427
/*mayBeInferred*/ false,
424428
[&](AccessScope typeAccessScope, const TypeRepr *complainRepr,
425429
DowngradeToWarning downgradeToWarning) {
430+
if (checkUsableFromInline) {
431+
auto diag = D->diagnose(diag::global_actor_not_usable_from_inline,
432+
D->getDescriptiveKind(), VD->getName());
433+
highlightOffendingType(diag, complainRepr);
434+
return;
435+
}
436+
426437
auto globalActorAccess = typeAccessScope.accessLevelForDiagnostics();
427438
bool isExplicit = D->getAttrs().hasAttribute<AccessControlAttr>();
428439
auto declAccess = isExplicit
429-
? D->getFormalAccess()
440+
? VD->getFormalAccess()
430441
: typeAccessScope.requiredAccessForDiagnostics();
431442
auto diag = D->diagnose(diag::global_actor_access, declAccess,
432-
D->getDescriptiveKind(), D->getName(),
443+
D->getDescriptiveKind(), VD->getName(),
433444
globalActorAccess, globalActorDecl->getName());
434445
highlightOffendingType(diag, complainRepr);
435446
});
@@ -451,9 +462,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
451462
return;
452463

453464
DeclVisitor<AccessControlChecker>::visit(D);
454-
455-
if (const auto *VD = dyn_cast<ValueDecl>(D))
456-
checkGlobalActorAccess(VD);
465+
checkGlobalActorAccess(D);
457466
}
458467

459468
// Force all kinds to be handled at a lower level.
@@ -1076,6 +1085,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
10761085
return;
10771086

10781087
DeclVisitor<UsableFromInlineChecker>::visit(D);
1088+
checkGlobalActorAccess(D);
10791089
}
10801090

10811091
// Force all kinds to be handled at a lower level.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 5
2+
3+
// REQUIRES: concurrency
4+
5+
@globalActor
6+
private struct PrivateGA { // expected-note 2 {{type declared here}}
7+
actor Actor {}
8+
static let shared = Actor()
9+
}
10+
11+
@globalActor
12+
internal struct InternalGA { // expected-note {{type declared here}}
13+
actor Actor {}
14+
static let shared = Actor()
15+
}
16+
17+
@globalActor @usableFromInline
18+
internal struct UFIGA {
19+
@usableFromInline actor Actor {}
20+
@usableFromInline static let shared = Actor()
21+
}
22+
23+
@globalActor
24+
public struct PublicGA {
25+
public actor Actor {}
26+
public static let shared = Actor()
27+
}
28+
29+
// expected-error@+1 {{internal struct 'UFIStructPrivateGA' cannot have private global actor 'PrivateGA'}}
30+
@PrivateGA @usableFromInline internal struct UFIStructPrivateGA {} // expected-error {{global actor for struct 'UFIStructPrivateGA' must be '@usableFromInline' or public}}
31+
@InternalGA @usableFromInline internal struct UFIStructInternalGA {} // expected-error {{global actor for struct 'UFIStructInternalGA' must be '@usableFromInline' or public}}
32+
@UFIGA @usableFromInline internal struct UFIStructUFIGA {}
33+
@PublicGA @usableFromInline internal struct UFIStructPublicGA {}

0 commit comments

Comments
 (0)