Skip to content

Commit eb8ef3f

Browse files
authored
Merge pull request #82082 from gottesmm/release/6.2-152596823
[6.2][silgen] Teach SILGen how to emit a forced dynamic member ref given nonisolated(nonsending) casts.
2 parents 5d24373 + 80ce07c commit eb8ef3f

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,37 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
17181718
return false;
17191719
}
17201720

1721+
static bool addsNonIsolatedNonSendingToAsyncFn(FunctionConversionExpr *fce) {
1722+
CanType oldTy = fce->getSubExpr()->getType()->getCanonicalType();
1723+
CanType newTy = fce->getType()->getCanonicalType();
1724+
1725+
if (auto oldFnTy = dyn_cast<AnyFunctionType>(oldTy)) {
1726+
if (auto newFnTy = dyn_cast<AnyFunctionType>(newTy)) {
1727+
// old type and new type MUST both be async
1728+
if (!oldFnTy->hasEffect(EffectKind::Async) ||
1729+
!newFnTy->hasEffect(EffectKind::Async))
1730+
return false;
1731+
1732+
// old type MUST NOT have nonisolated(nonsending).
1733+
if (oldFnTy->getIsolation().isNonIsolatedCaller())
1734+
return false;
1735+
1736+
// new type MUST nonisolated(nonsending)
1737+
if (!newFnTy->getIsolation().isNonIsolatedCaller())
1738+
return false;
1739+
1740+
// See if setting isolation of old type to nonisolated(nonsending)
1741+
// yields the new type.
1742+
auto addedNonIsolatedNonSending = oldFnTy->getExtInfo().withIsolation(
1743+
FunctionTypeIsolation::forNonIsolatedCaller());
1744+
1745+
return oldFnTy->withExtInfo(addedNonIsolatedNonSending) == newFnTy;
1746+
}
1747+
}
1748+
1749+
return false;
1750+
}
1751+
17211752
/// Ignore parentheses and implicit conversions.
17221753
static Expr *ignoreParensAndImpConversions(Expr *expr) {
17231754
while (true) {
@@ -1738,6 +1769,8 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
17381769
if (auto funcConv = dyn_cast<FunctionConversionExpr>(nextSubExpr)) {
17391770
if (addsGlobalActorToAsyncFn(funcConv))
17401771
nextSubExpr = funcConv->getSubExpr();
1772+
else if (addsNonIsolatedNonSendingToAsyncFn(funcConv))
1773+
nextSubExpr = funcConv->getSubExpr();
17411774
}
17421775

17431776
if (auto bind = dyn_cast<BindOptionalExpr>(nextSubExpr)) {
@@ -1775,7 +1808,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
17751808

17761809
auto openExistential = dyn_cast<OpenExistentialExpr>(arg);
17771810
if (openExistential)
1778-
arg = openExistential->getSubExpr();
1811+
arg = ignoreParensAndImpConversions(openExistential->getSubExpr());
17791812

17801813
auto dynamicMemberRef = dyn_cast<DynamicMemberRefExpr>(arg);
17811814
if (!dynamicMemberRef)

test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ typedef void (^NonsendableCompletionHandler)(NSString * _Nullable, NSString * _N
133133
(void (^)(NSString *__nullable value,
134134
NSError *__nullable error))completionHandler
135135
MAIN_ACTOR;
136+
137+
- (void)startAt:(__nullable NSDate *)value
138+
completion:(void (^_Nonnull)(void))completion;
136139
@end
137140

138141
@protocol RefrigeratorDelegate<NSObject>

test/SILGen/objc_async.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,31 @@ extension SlowServer: @retroactive FailableFloatLoader {
360360
// CHECK-NEXT: [[ZERO_FLOAT:%.*]] = builtin "zeroInitializer"() : $Float
361361
// CHECK-NEXT: [[BORROWED_SOME_NSERROR:%.*]] = begin_borrow [[SOME_NSERROR]] :
362362
// CHECK-NEXT: apply [[BORROWED_BLOCK]]([[ZERO_FLOAT]], [[BORROWED_SOME_NSERROR]])
363+
364+
// CHECK-LABEL: sil hidden [ossa] @$s10objc_async13testAnyObjectyySo10SlowServerCYaF : $@convention(thin) @async (@guaranteed SlowServer) -> () {
365+
// CHECK: bb0([[SLOWSERVER:%.*]] : @guaranteed $SlowServer):
366+
// CHECK: [[SLOWSERVER_C:%.*]] = copy_value [[SLOWSERVER]]
367+
// CHECK: [[SLOWSERVER_ANYOBJECT:%.*]] = init_existential_ref [[SLOWSERVER_C]]
368+
// CHECK: [[SLOWSERVER_ANYOBJECT_M:%.*]] = move_value [lexical] [var_decl] [[SLOWSERVER_ANYOBJECT]]
369+
// CHECK: debug_value [[SLOWSERVER_ANYOBJECT_M]] : $AnyObject, let, name "anyObjectSlowServer"
370+
// CHECK: [[SLOWSERVER_ANYOBJECT_M_B:%.*]] = begin_borrow [[SLOWSERVER_ANYOBJECT_M]]
371+
// CHECK: [[SLOWSERVER_ANYOBJECT_M_B_O:%.*]] = open_existential_ref [[SLOWSERVER_ANYOBJECT_M_B]]
372+
// CHECK: [[SLOWSERVER_ANYOBJECT_M_B_O_C:%.*]] = copy_value [[SLOWSERVER_ANYOBJECT_M_B_O]]
373+
// CHECK: [[METHOD:%.*]] = objc_method [[SLOWSERVER_ANYOBJECT_M_B_O_C]] : $@opened("{{.*}}", AnyObject) Self, #SlowServer.start!foreign : (SlowServer) -> (NSDate?) async -> (), $@convention(objc_method) (Optional<NSDate>, @convention(block) @Sendable () -> (), @opened("{{.*}}", AnyObject) Self) -> ()
374+
// CHECK: [[CONT:%.*]] = get_async_continuation_addr ()
375+
// CHECK: [[UNSAFE_CONT:%.*]] = struct $UnsafeContinuation<(), Never> ([[CONT]] : $Builtin.RawUnsafeContinuation)
376+
// CHECK: [[BLOCK:%.*]] = alloc_stack $@block_storage Any
377+
// CHECK: [[BLOCK_PROJECT:%.*]] = project_block_storage [[BLOCK]]
378+
// CHECK: [[BLOCK_PROJECT_EX:%.*]] = init_existential_addr [[BLOCK_PROJECT]]
379+
// CHECK: store [[UNSAFE_CONT]] to [trivial] [[BLOCK_PROJECT_EX]]
380+
// CHECK: merge_isolation_region [[BLOCK]] : $*@block_storage Any,
381+
// CHECK: [[CONT_HANDLER:%.*]] = function_ref @$sIeyBh_ytTz_ : $@convention(c) @Sendable (@inout_aliasable @block_storage Any) -> ()
382+
// CHECK: [[INIT_BLOCK_STORAGE_HEADER:%.*]] = init_block_storage_header [[BLOCK]] : $*@block_storage Any, invoke [[CONT_HANDLER]]
383+
// CHECK: merge_isolation_region [[SLOWSERVER_ANYOBJECT_M_B_O_C]] : $@opened("{{.*}}", AnyObject) Self, [[BLOCK]]
384+
// CHECK: apply [[METHOD]]({{%.*}}, [[INIT_BLOCK_STORAGE_HEADER]], [[SLOWSERVER_ANYOBJECT_M_B_O_C]])
385+
// CHECK: await_async_continuation [[CONT]] : $Builtin.RawUnsafeContinuation, resume bb1
386+
// CHECK: } // end sil function '$s10objc_async13testAnyObjectyySo10SlowServerCYaF'
387+
func testAnyObject(_ slowServer: SlowServer) async {
388+
let anyObjectSlowServer: AnyObject = slowServer
389+
await anyObjectSlowServer.start(at: nil)
390+
}

0 commit comments

Comments
 (0)