Skip to content

Commit 171dadc

Browse files
authored
Merge pull request #84409 from xedin/rdar-157663660
[Concurrency] Prevent some extraneous function conversion sendability checking
2 parents a44bf30 + ce33100 commit 171dadc

File tree

2 files changed

+54
-22
lines changed

2 files changed

+54
-22
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2666,7 +2666,8 @@ namespace {
26662666

26672667
/// Some function conversions synthesized by the constraint solver may not
26682668
/// be correct AND the solver doesn't know, so we must emit a diagnostic.
2669-
void checkFunctionConversion(Expr *funcConv, Type fromType, Type toType) {
2669+
void checkFunctionConversion(ImplicitConversionExpr *funcConv,
2670+
Type fromType, Type toType) {
26702671
auto diagnoseNonSendableParametersAndResult =
26712672
[&](FunctionType *fnType,
26722673
std::optional<unsigned> warnUntilSwiftMode = std::nullopt) {
@@ -2771,6 +2772,18 @@ namespace {
27712772
if (!fromFnType->isAsync())
27722773
break;
27732774

2775+
// Applying `nonisolated(nonsending)` to an interface type
2776+
// of a declaration.
2777+
if (auto *declRef =
2778+
dyn_cast<DeclRefExpr>(funcConv->getSubExpr())) {
2779+
auto *decl = declRef->getDecl();
2780+
if (auto *nonisolatedAttr =
2781+
decl->getAttrs().getAttribute<NonisolatedAttr>()) {
2782+
if (nonisolatedAttr->isNonSending())
2783+
return;
2784+
}
2785+
}
2786+
27742787
// @concurrent -> nonisolated(nonsending)
27752788
// crosses an isolation boundary.
27762789
LLVM_FALLTHROUGH;
@@ -2780,16 +2793,13 @@ namespace {
27802793
diagnoseNonSendableParametersAndResult(toFnType);
27812794
break;
27822795

2783-
case FunctionTypeIsolation::Kind::Parameter:
2784-
llvm_unreachable("invalid conversion");
2785-
2796+
// @Sendable nonisolated(nonsending) -> nonisolated(nonsending)
2797+
// doesn't require Sendable checking.
27862798
case FunctionTypeIsolation::Kind::NonIsolatedNonsending:
2787-
// Non isolated caller is always async. This can only occur if we
2788-
// are converting from an `@Sendable` representation to something
2789-
// else. So we need to just check that we diagnose non sendable
2790-
// parameters and results.
2791-
diagnoseNonSendableParametersAndResult(toFnType);
27922799
break;
2800+
2801+
case FunctionTypeIsolation::Kind::Parameter:
2802+
llvm_unreachable("invalid conversion");
27932803
}
27942804
break;
27952805
}
@@ -3460,19 +3470,6 @@ namespace {
34603470
}
34613471
}
34623472

3463-
// The constraint solver may not have chosen legal casts.
3464-
if (auto funcConv = dyn_cast<FunctionConversionExpr>(expr)) {
3465-
checkFunctionConversion(funcConv,
3466-
funcConv->getSubExpr()->getType(),
3467-
funcConv->getType());
3468-
}
3469-
3470-
if (auto *isolationErasure = dyn_cast<ActorIsolationErasureExpr>(expr)) {
3471-
checkFunctionConversion(isolationErasure,
3472-
isolationErasure->getSubExpr()->getType(),
3473-
isolationErasure->getType());
3474-
}
3475-
34763473
if (auto *defaultArg = dyn_cast<DefaultArgumentExpr>(expr)) {
34773474
checkDefaultArgument(defaultArg);
34783475
}
@@ -3564,6 +3561,19 @@ namespace {
35643561
}
35653562
}
35663563

3564+
// The constraint solver may not have chosen legal casts.
3565+
if (auto funcConv = dyn_cast<FunctionConversionExpr>(expr)) {
3566+
checkFunctionConversion(funcConv,
3567+
funcConv->getSubExpr()->getType(),
3568+
funcConv->getType());
3569+
}
3570+
3571+
if (auto *isolationErasure = dyn_cast<ActorIsolationErasureExpr>(expr)) {
3572+
checkFunctionConversion(isolationErasure,
3573+
isolationErasure->getSubExpr()->getType(),
3574+
isolationErasure->getType());
3575+
}
3576+
35673577
return Action::Continue(expr);
35683578
}
35693579

test/Concurrency/attr_execution/conversions_silgen.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,4 +620,26 @@ func testSendableClosureNonisolatedNonSendingInference() {
620620
// CHECK: hop_to_executor [[EXECUTOR]]
621621
// CHECK: // end sil function '$s21attr_execution_silgen49testSendableClosureNonisolatedNonSendingInferenceyyFySiYaYbYCcfU_'
622622
let _: nonisolated(nonsending) @Sendable (Int) async -> Void = { _ in }
623+
624+
// CHECK-LABEL: sil private [ossa] @$s21attr_execution_silgen49testSendableClosureNonisolatedNonSendingInferenceyyFyS2SYaKYCcYaYbYCcfU0_ : $@convention(thin) @Sendable @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String) -> (@owned String, @error any Error)) -> @error any Error
625+
// CHECK: bb0([[EXECUTOR:%.*]] : @guaranteed $Optional<any Actor>, %1 : @guaranteed $@async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String) -> (@owned String, @error any Error)):
626+
// CHECK: hop_to_executor [[EXECUTOR]]
627+
// CHECK: // end sil function '$s21attr_execution_silgen49testSendableClosureNonisolatedNonSendingInferenceyyFyS2SYaKYCcYaYbYCcfU0_'
628+
let _: nonisolated(nonsending) @Sendable (
629+
nonisolated(nonsending) @escaping (String) async throws -> String
630+
) async throws -> Void = { _ in }
631+
}
632+
633+
// CHECK-LABEL: sil hidden [ossa] @$s21attr_execution_silgen014testSendableToE35ConversionWithNonisilatedNonsendingyyF : $@convention(thin) () -> ()
634+
// CHECK: [[TEST_REF:%.*]] = function_ref @$s21attr_execution_silgen014testSendableToE35ConversionWithNonisilatedNonsendingyyF0D0L_7closureyS2SYaKYCc_tYaYbKF : $@convention(thin) @Sendable @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String) -> (@owned String, @error any Error)) -> @error any Error
635+
// CHECK: // end sil function '$s21attr_execution_silgen014testSendableToE35ConversionWithNonisilatedNonsendingyyF'
636+
func testSendableToSendableConversionWithNonisilatedNonsending() {
637+
@Sendable nonisolated(nonsending) func test(
638+
closure: nonisolated(nonsending) @escaping (String) async throws -> String
639+
) async throws {
640+
}
641+
642+
let _: nonisolated(nonsending) @Sendable (
643+
nonisolated(nonsending) @escaping (String) async throws -> String
644+
) async throws -> Void = test
623645
}

0 commit comments

Comments
 (0)