Skip to content

Commit c352ec8

Browse files
committed
Respect @preconcurrency for instance properties of non-sendable types in deinit
Instance properties of non-sendable types cannot safely be accessed within deinitializers. Make sure we respect `@preconcurrency` when diagnosing these. (cherry picked from commit c326fd3)
1 parent 6c197f5 commit c352ec8

File tree

8 files changed

+57
-27
lines changed

8 files changed

+57
-27
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -692,9 +692,6 @@ ERROR(isolated_after_nonisolated, none,
692692
NOTE(nonisolated_blame, none, "after %1%2 %3, "
693693
"only non-isolated properties of 'self' can be accessed from "
694694
"%select{this init|a deinit}0", (bool, StringRef, StringRef, DeclName))
695-
ERROR(non_sendable_from_deinit,none,
696-
"cannot access %1 %2 with a non-sendable type %0 from non-isolated deinit",
697-
(Type, DescriptiveDeclKind, DeclName))
698695
ERROR(isolated_property_mutation_in_nonisolated_context,none,
699696
"actor-isolated %kind0 can not be %select{referenced|mutated}1 "
700697
"from a non-isolated context",

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5757,6 +5757,10 @@ ERROR(nonisolated_wrapped_property,none,
57575757
"'nonisolated' is not supported on properties with property wrappers",
57585758
())
57595759

5760+
ERROR(non_sendable_from_deinit,none,
5761+
"cannot access %1 %2 with a non-sendable type %0 from non-isolated deinit",
5762+
(Type, DescriptiveDeclKind, DeclName))
5763+
57605764
ERROR(actor_instance_property_wrapper,none,
57615765
"%0 property in property wrapper type %1 cannot be isolated to "
57625766
"the actor instance; consider 'nonisolated'",

include/swift/Sema/Concurrency.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222

2323
namespace swift {
2424

25+
class DeclContext;
2526
class SourceFile;
2627
class NominalTypeDecl;
28+
class VarDecl;
2729

2830
/// If any of the imports in this source file was @preconcurrency but there were
2931
/// no diagnostics downgraded or suppressed due to that @preconcurrency, suggest
@@ -35,6 +37,13 @@ void diagnoseUnnecessaryPreconcurrencyImports(SourceFile &sf);
3537
bool hasExplicitSendableConformance(NominalTypeDecl *nominal,
3638
bool applyModuleDefault = true);
3739

40+
/// Diagnose the use of an instance property of non-sendable type from an
41+
/// nonisolated deinitializer within an actor-isolated type.
42+
///
43+
/// \returns true iff a diagnostic was emitted for this reference.
44+
bool diagnoseNonSendableFromDeinit(
45+
SourceLoc refLoc, VarDecl *var, DeclContext *dc);
46+
3847
} // namespace swift
3948

4049
#endif

lib/SILOptimizer/Mandatory/FlowIsolation.cpp

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/AST/Expr.h"
1717
#include "swift/AST/ActorIsolation.h"
1818
#include "swift/AST/DiagnosticsSIL.h"
19+
#include "swift/Sema/Concurrency.h"
1920
#include "swift/SIL/ApplySite.h"
2021
#include "swift/SIL/BitDataflow.h"
2122
#include "swift/SIL/BasicBlockBits.h"
@@ -528,31 +529,17 @@ static bool onlyDeinitAccess(RefElementAddrInst *inst) {
528529
/// is happening in a deinit that uses flow-isolation.
529530
/// \returns true iff a diagnostic was emitted for this reference.
530531
static bool diagnoseNonSendableFromDeinit(RefElementAddrInst *inst) {
531-
VarDecl *var = inst->getField();
532-
Type ty = var->getTypeInContext();
533-
DeclContext *dc = inst->getFunction()->getDeclContext();
532+
auto dc = inst->getFunction()->getDeclContext();
534533

535-
// FIXME: we should emit diagnostics in other modes using:
536-
//
537-
// if (!shouldDiagnoseExistingDataRaces(dc))
538-
// return false;
539-
//
540-
// but until we decide how we want to handle isolated state from deinits,
541-
// we're going to limit the noise to complete mode for now.
534+
// For historical reasons, only diagnose this issue in strict mode.
542535
if (dc->getASTContext().LangOpts.StrictConcurrencyLevel
543-
!= StrictConcurrency::Complete)
544-
return false;
545-
546-
if (ty->isSendableType())
536+
!= StrictConcurrency::Complete)
547537
return false;
548538

549-
auto &diag = var->getASTContext().Diags;
550-
551-
diag.diagnose(inst->getLoc().getSourceLoc(), diag::non_sendable_from_deinit,
552-
ty, var->getDescriptiveKind(), var->getName())
553-
.warnUntilSwiftVersion(6);
554-
555-
return true;
539+
return swift::diagnoseNonSendableFromDeinit(
540+
inst->getLoc().getSourceLoc(),
541+
inst->getField(),
542+
dc);
556543
}
557544

558545
class OperandWorklist {

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6830,3 +6830,14 @@ ActorReferenceResult ActorReferenceResult::forReference(
68306830

68316831
return forEntersActor(declIsolation, options);
68326832
}
6833+
6834+
bool swift::diagnoseNonSendableFromDeinit(
6835+
SourceLoc refLoc, VarDecl *var, DeclContext *dc) {
6836+
return diagnoseIfAnyNonSendableTypes(var->getTypeInContext(),
6837+
SendableCheckContext(dc),
6838+
Type(),
6839+
SourceLoc(),
6840+
refLoc,
6841+
diag::non_sendable_from_deinit,
6842+
var->getDescriptiveKind(), var->getName());
6843+
}

test/Concurrency/flow_isolation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func takeNonSendable(_ ns: NonSendableType) {}
1515
@available(SwiftStdlib 5.1, *)
1616
func takeSendable(_ s: SendableType) {}
1717

18-
class NonSendableType {
18+
class NonSendableType { // expected-note *{{class 'NonSendableType' does not conform to the 'Sendable' protocol}}
1919
var x: Int = 0
2020
func f() {}
2121
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/StrictModule.swiftmodule -module-name StrictModule -swift-version 6 %S/Inputs/StrictModule.swift
3+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/NonStrictModule.swiftmodule -module-name NonStrictModule %S/Inputs/NonStrictModule.swift
4+
5+
// RUN: %target-swift-frontend -I %t %s -emit-sil -o /dev/null -verify -strict-concurrency=complete
6+
7+
// REQUIRES: concurrency
8+
// REQUIRES: asserts
9+
10+
@preconcurrency import NonStrictModule
11+
@preconcurrency import StrictModule
12+
13+
@available(SwiftStdlib 5.1, *)
14+
actor ActorWithDeinit {
15+
var ns: NonStrictClass = NonStrictClass()
16+
var ss: StrictStruct = StrictStruct()
17+
18+
deinit {
19+
print(ns)
20+
print(ss) // expected-warning{{cannot access property 'ss' with a non-sendable type 'StrictStruct' from non-isolated deinit}}
21+
}
22+
}

test/Concurrency/predates_concurrency_import_swift6.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/StrictModule.swiftmodule -module-name StrictModule -swift-version 6 %S/Inputs/StrictModule.swift
33
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/NonStrictModule.swiftmodule -module-name NonStrictModule %S/Inputs/NonStrictModule.swift
44

5-
// RUN: %target-swift-frontend -swift-version 6 -I %t %s %s -emit-sil -o /dev/null -verify -parse-as-library
6-
// RUN: %target-swift-frontend -swift-version 6 -I %t %s %s -emit-sil -o /dev/null -verify -enable-upcoming-feature RegionBasedIsolation -parse-as-library
5+
// RUN: %target-swift-frontend -swift-version 6 -I %t %s -emit-sil -o /dev/null -verify -parse-as-library
6+
// RUN: %target-swift-frontend -swift-version 6 -I %t %s -emit-sil -o /dev/null -verify -enable-upcoming-feature RegionBasedIsolation -parse-as-library
77

88
@preconcurrency import NonStrictModule
99
@preconcurrency import StrictModule

0 commit comments

Comments
 (0)