Skip to content

Commit c9b5791

Browse files
committed
[Concurrency] Diagnose redundant (unsafe) for a public actor-isolated Sendable immutable storage.
1 parent b6b28dd commit c9b5791

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5690,6 +5690,10 @@ WARNING(nonisolated_unsafe_sendable_constant,none,
56905690
"'nonisolated(unsafe)' is unnecessary for a constant with 'Sendable' type "
56915691
"%0, consider removing it",
56925692
(Type))
5693+
WARNING(unsafe_sendable_actor_constant,none,
5694+
"'(unsafe)' is unnecessary for a constant public actor property with "
5695+
"'Sendable' type %0, consider removing it",
5696+
(Type))
56935697
ERROR(nonisolated_non_sendable,none,
56945698
"'nonisolated' can not be applied to variable with non-'Sendable' "
56955699
"type %0",

lib/Sema/TypeCheckAttr.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6926,8 +6926,27 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
69266926
if (attr->isUnsafe() &&
69276927
type->isSendableType() &&
69286928
var->isLet()) {
6929-
diagnoseAndRemoveAttr(
6930-
attr, diag::nonisolated_unsafe_sendable_constant, type);
6929+
6930+
// '(unsafe)' is redundant for a public actor-isolated 'Sendable'
6931+
// immutable.
6932+
auto nominal = dyn_cast<NominalTypeDecl>(dc);
6933+
if (nominal && nominal->isActor()) {
6934+
auto access = nominal->getFormalAccessScope(
6935+
/*useDC=*/nullptr,
6936+
/*treatUsableFromInlineAsPublic=*/true);
6937+
if (access.isPublic()) {
6938+
// Get the location where '(unsafe)' starts.
6939+
SourceLoc unsafeStart = Lexer::getLocForEndOfToken(
6940+
Ctx.SourceMgr, attr->getRange().Start);
6941+
diagnose(unsafeStart, diag::unsafe_sendable_actor_constant, type)
6942+
.fixItRemoveChars(unsafeStart,
6943+
attr->getRange().End.getAdvancedLoc(1));
6944+
}
6945+
6946+
} else {
6947+
diagnoseAndRemoveAttr(
6948+
attr, diag::nonisolated_unsafe_sendable_constant, type);
6949+
}
69316950
}
69326951
}
69336952

test/Concurrency/global_variables.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ struct TestStatics {
5454
// expected-note@-1{{isolate 'wrapped' to a global actor, or convert it to a 'let' constant and conform it to 'Sendable'}}
5555
}
5656

57+
public actor TestPublicActor {
58+
nonisolated(unsafe) let immutableNonisolatedUnsafeSendable = TestSendable()
59+
// expected-warning@-1 {{'(unsafe)' is unnecessary for a constant public actor property with 'Sendable' type 'TestSendable', consider removing it}} {{14-22=}}
60+
}
61+
5762
@TestGlobalActor
5863
func f() {
5964
print(TestStatics.immutableExplicitSendable)

0 commit comments

Comments
 (0)