Skip to content

Commit 65d6af6

Browse files
committed
Diagnose key paths that capture non-concurrent values.
1 parent 26bbd8c commit 65d6af6

File tree

4 files changed

+36
-30
lines changed

4 files changed

+36
-30
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4316,6 +4316,9 @@ WARNING(non_concurrent_property_type,none,
43164316
"cannot use %0 %1 with a non-concurrent-value type %2 "
43174317
"%select{across actors|from concurrently-executed code}3",
43184318
(DescriptiveDeclKind, DeclName, Type, bool))
4319+
WARNING(non_concurrent_keypath_capture,none,
4320+
"cannot form key path that captures non-concurrent-value type %0",
4321+
(Type))
43194322
ERROR(non_concurrent_type_member,none,
43204323
"%select{stored property %1|associated value %1}0 of "
43214324
"'ConcurrentValue'-conforming %2 %3 has non-concurrent-value type %4",

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,22 @@ namespace {
11111111
}
11121112
}
11131113

1114+
// Key paths require any captured values to be ConcurrentValue-conforming.
1115+
if (auto keyPath = dyn_cast<KeyPathExpr>(expr)) {
1116+
for (const auto &component : keyPath->getComponents()) {
1117+
auto indexExpr = component.getIndexExpr();
1118+
if (!indexExpr || !indexExpr->getType())
1119+
continue;
1120+
1121+
if (ctx.LangOpts.EnableExperimentalConcurrentValueChecking &&
1122+
!isConcurrentValueType(getDeclContext(), indexExpr->getType())) {
1123+
ctx.Diags.diagnose(
1124+
component.getLoc(), diag::non_concurrent_keypath_capture,
1125+
indexExpr->getType());
1126+
}
1127+
}
1128+
}
1129+
11141130
// The children of #selector expressions are not evaluated, so we do not
11151131
// need to do isolation checking there. This is convenient because such
11161132
// expressions tend to violate restrictions on the use of instance

lib/Sema/TypeCheckConcurrency.h

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -66,36 +66,6 @@ enum class ConcurrentReferenceKind {
6666
ConcurrentFunction,
6767
};
6868

69-
/// Describes why or where a particular entity has a non-concurrent-value type.
70-
struct NonConcurrentType {
71-
enum Kind {
72-
/// A function parameter is a non-concurrent-value type.
73-
Parameter,
74-
/// The result of a function is a non-concurrent-value type.
75-
Result,
76-
/// The type of a property is a non-concurrent-value type.
77-
Property,
78-
} kind;
79-
80-
/// The declaration reference.
81-
ConcreteDeclRef declRef;
82-
83-
/// The non-concurrent-value type being diagnosed.
84-
Type type;
85-
86-
/// Determine whether a reference to the given declaration involves a
87-
/// non-concurrent-value type. If it does, return the reason. Otherwise,
88-
/// return \c None.
89-
///
90-
/// \param dc The declaration context from which the reference occurs.
91-
/// \param declRef The reference to the declaration.
92-
static Optional<NonConcurrentType> get(
93-
const DeclContext *dc, ConcreteDeclRef declRef);
94-
95-
/// Diagnose the non-concurrent-value type at the given source location.
96-
void diagnose(SourceLoc loc);
97-
};
98-
9969
/// The isolation restriction in effect for a given declaration that is
10070
/// referenced from source.
10171
class ActorIsolationRestriction {

test/Concurrency/concurrent_value_checking.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,23 @@ func testConcurrency() {
122122
}
123123
}
124124

125+
// ----------------------------------------------------------------------
126+
// ConcurrentValue restriction on key paths.
127+
// ----------------------------------------------------------------------
128+
class NC: Hashable {
129+
func hash(into: inout Hasher) { }
130+
static func==(_: NC, _: NC) -> Bool { true }
131+
}
132+
133+
class HasNC {
134+
var dict: [NC: Int] = [:]
135+
}
136+
137+
func testKeyPaths(dict: [NC: Int], nc: NC) {
138+
_ = \HasNC.dict[nc] // expected-warning{{cannot form key path that captures non-concurrent-value type 'NC'}}
139+
}
140+
141+
125142
// ----------------------------------------------------------------------
126143
// ConcurrentValue restriction on conformances.
127144
// ----------------------------------------------------------------------

0 commit comments

Comments
 (0)