Skip to content

Commit e2f9267

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

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5700,6 +5700,10 @@ WARNING(nonisolated_unsafe_sendable_constant,none,
57005700
"'nonisolated(unsafe)' is unnecessary for a constant with 'Sendable' type "
57015701
"%0, consider removing it",
57025702
(Type))
5703+
WARNING(unsafe_sendable_actor_constant,none,
5704+
"'(unsafe)' is unnecessary for a constant public actor property with "
5705+
"'Sendable' type %0, consider removing it",
5706+
(Type))
57035707
ERROR(nonisolated_non_sendable,none,
57045708
"'nonisolated' can not be applied to variable with non-'Sendable' "
57055709
"type %0",

lib/Sema/TypeCheckAttr.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6926,9 +6926,28 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
69266926
if (attr->isUnsafe() &&
69276927
type->isSendableType() &&
69286928
var->isLet()) {
6929-
diagnose(attr->getLocation(),
6930-
diag::nonisolated_unsafe_sendable_constant, type)
6931-
.fixItRemove(attr->getRange());
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+
diagnose(attr->getLocation(),
6948+
diag::nonisolated_unsafe_sendable_constant, type)
6949+
.fixItRemove(attr->getRange());
6950+
}
69326951
}
69336952
}
69346953

test/Concurrency/global_variables.swift

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

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

0 commit comments

Comments
 (0)