Skip to content

Commit 5af310a

Browse files
committed
[Concurrency] Don't diagnose non-ConcurrentValue parameters/result type of @Concurrent functions.
Thanks to Jordan Rose and John McCall, who pointed out why this checking was unnecessary. As a drive-by, ensure that we diagnose parameter references properly.
1 parent 7be05de commit 5af310a

File tree

5 files changed

+10
-66
lines changed

5 files changed

+10
-66
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4312,10 +4312,6 @@ WARNING(non_concurrent_property_type,none,
43124312
"cannot use %0 %1 with a non-concurrent-value type %2 "
43134313
"%select{across actors|from concurrently-executed code}3",
43144314
(DescriptiveDeclKind, DeclName, Type, bool))
4315-
WARNING(non_concurrent_function_type,none,
4316-
"`@concurrent` %select{function type|closure}0 has "
4317-
"non-concurrent-value %select{parameter|result}1 type %2",
4318-
(bool, bool, Type))
43194315
ERROR(non_concurrent_type_member,none,
43204316
"%select{stored property %1|associated value %1}0 of "
43214317
"'ConcurrentValue'-conforming %2 %3 has non-concurrent-value type %4",

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,9 @@ bool swift::diagnoseNonConcurrentTypesInReference(
905905
}
906906

907907
if (auto var = dyn_cast<VarDecl>(declRef.getDecl())) {
908-
Type propertyType = var->getValueInterfaceType().subst(subs);
908+
Type propertyType = var->isLocalCapture()
909+
? var->getType()
910+
: var->getValueInterfaceType().subst(subs);
909911
if (!isConcurrentValueType(dc, propertyType)) {
910912
return diagnoseNonConcurrentProperty(loc, refKind, var, propertyType);
911913
}
@@ -932,35 +934,6 @@ bool swift::diagnoseNonConcurrentTypesInReference(
932934
return false;
933935
}
934936

935-
bool swift::diagnoseNonConcurrentTypesInFunctionType(
936-
const AnyFunctionType *fnType, const DeclContext *dc, SourceLoc loc,
937-
bool isClosure) {
938-
ASTContext &ctx = dc->getASTContext();
939-
// Bail out immediately if we aren't supposed to do this checking.
940-
if (!dc->getASTContext().LangOpts.EnableExperimentalConcurrentValueChecking)
941-
return false;
942-
943-
// Check parameter types.
944-
for (const auto &param : fnType->getParams()) {
945-
Type paramType = param.getParameterType();
946-
if (!isConcurrentValueType(dc, paramType)) {
947-
ctx.Diags.diagnose(
948-
loc, diag::non_concurrent_function_type, isClosure, false, paramType);
949-
return true;
950-
}
951-
}
952-
953-
// Check result type.
954-
if (!isConcurrentValueType(dc, fnType->getResult())) {
955-
ctx.Diags.diagnose(
956-
loc, diag::non_concurrent_function_type, isClosure, true,
957-
fnType->getResult());
958-
return true;
959-
}
960-
961-
return false;
962-
}
963-
964937
namespace {
965938
/// Check for adherence to the actor isolation rules, emitting errors
966939
/// when actor-isolated declarations are used in an unsafe manner.
@@ -1113,18 +1086,6 @@ namespace {
11131086
if (auto *closure = dyn_cast<AbstractClosureExpr>(expr)) {
11141087
closure->setActorIsolation(determineClosureIsolation(closure));
11151088
contextStack.push_back(closure);
1116-
1117-
1118-
// Concurrent closures must be composed of concurrent-safe parameter
1119-
// and result types.
1120-
if (isConcurrentClosure(closure)) {
1121-
if (auto fnType = closure->getType()->getAs<FunctionType>()) {
1122-
(void)diagnoseNonConcurrentTypesInFunctionType(
1123-
fnType, getDeclContext(), closure->getLoc(),
1124-
/*isClosure=*/true);
1125-
}
1126-
}
1127-
11281089
return { true, expr };
11291090
}
11301091

lib/Sema/TypeCheckConcurrency.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,6 @@ bool diagnoseNonConcurrentTypesInReference(
237237
ConcreteDeclRef declRef, const DeclContext *dc, SourceLoc loc,
238238
ConcurrentReferenceKind refKind);
239239

240-
/// Diagnose the presence of any non-concurrent types within the given
241-
/// function type.
242-
bool diagnoseNonConcurrentTypesInFunctionType(
243-
const AnyFunctionType *fnType, const DeclContext *dc, SourceLoc loc,
244-
bool isClosure);
245-
246240
/// Check the correctness of the given ConcurrentValue conformance.
247241
void checkConcurrentValueConformance(ProtocolConformance *conformance);
248242

lib/Sema/TypeCheckType.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,14 +2823,6 @@ NeverNullType TypeResolver::resolveASTFunctionType(
28232823
if (fnTy->hasError())
28242824
return fnTy;
28252825

2826-
// Concurrent function types must be composed of concurrent-safe parameter
2827-
// and result types.
2828-
if (concurrent && resolution.getStage() > TypeResolutionStage::Structural) {
2829-
(void)diagnoseNonConcurrentTypesInFunctionType(
2830-
fnTy, resolution.getDeclContext(), repr->getLoc(),
2831-
/*isClosure=*/false);
2832-
}
2833-
28342826
// If the type is a block or C function pointer, it must be representable in
28352827
// ObjC.
28362828
switch (representation) {

test/Concurrency/concurrent_value_checking.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,22 +151,23 @@ class SomeClass: MainActorProto {
151151
@concurrent func concurrentFunc() -> NotConcurrent? { nil } // expected-warning{{cannot call function returning non-concurrent-value type 'NotConcurrent?' across actors}}
152152

153153
// ----------------------------------------------------------------------
154-
// ConcurrentValue restriction on @concurrent types.
154+
// No ConcurrentValue restriction on @concurrent function types.
155155
// ----------------------------------------------------------------------
156-
typealias CF = @concurrent () -> NotConcurrent? // expected-warning{{`@concurrent` function type has non-concurrent-value result type 'NotConcurrent?'}}
157-
typealias BadGenericCF<T> = @concurrent () -> T? // expected-warning{{`@concurrent` function type has non-concurrent-value result type 'T?'}}
156+
typealias CF = @concurrent () -> NotConcurrent?
157+
typealias BadGenericCF<T> = @concurrent () -> T?
158158
typealias GoodGenericCF<T: ConcurrentValue> = @concurrent () -> T? // okay
159159

160-
var concurrentFuncVar: (@concurrent (NotConcurrent) -> Void)? = nil // expected-warning{{`@concurrent` function type has non-concurrent-value parameter type 'NotConcurrent'}}
160+
var concurrentFuncVar: (@concurrent (NotConcurrent) -> Void)? = nil
161161

162162
// ----------------------------------------------------------------------
163163
// ConcurrentValue restriction on @concurrent closures.
164164
// ----------------------------------------------------------------------
165165
func acceptConcurrentUnary<T>(_: @concurrent (T) -> T) { }
166166

167167
func concurrentClosures<T>(_: T) {
168-
acceptConcurrentUnary { (x: T) in // expected-warning{{`@concurrent` closure has non-concurrent-value parameter type 'T'}}
169-
x
168+
acceptConcurrentUnary { (x: T) in
169+
_ = x // ok
170+
acceptConcurrentUnary { _ in x } // expected-warning{{cannot use parameter 'x' with a non-concurrent-value type 'T' from concurrently-executed code}}
170171
}
171172
}
172173

0 commit comments

Comments
 (0)