Skip to content

Commit 36c821c

Browse files
committed
Mandatory Inlining: Set ApplyOptions correctly in TypeSubstCloner
When we inline an async function called via 'apply [noasync]' or 'try_apply [noasync]', we must in turn set the '[noasync]' flag on any async functions that the inlined function calls.
1 parent d8d6da8 commit 36c821c

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

include/swift/SIL/ApplySite.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ class ApplySite {
452452
case ApplySiteKind::TryApplyInst:
453453
return cast<TryApplyInst>(Inst)->getApplyOptions();
454454
case ApplySiteKind::PartialApplyInst:
455-
llvm_unreachable("Unhandled case");
455+
return ApplyOptions();
456456
}
457457
}
458458
/// Return whether the given apply is of a formally-throwing function

include/swift/SIL/TypeSubstCloner.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
5454
SubstitutionMap Subs;
5555
SmallVector<SILValue, 8> Args;
5656
SubstitutionMap RecursiveSubs;
57+
ApplyOptions ApplyOpts;
5758

5859
public:
5960
ApplySiteCloningHelper(ApplySite AI, TypeSubstCloner &Cloner)
@@ -67,6 +68,14 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
6768
// Remap substitutions.
6869
Subs = Cloner.getOpSubstitutionMap(AI.getSubstitutionMap());
6970

71+
// If we're inlining a [noasync] function, make sure any calls inside it
72+
// are marked as [noasync] as appropriate.
73+
ApplyOpts = AI.getApplyOptions();
74+
if (!Builder.getFunction().isAsync() &&
75+
SubstCalleeSILType.castTo<SILFunctionType>()->isAsync()) {
76+
ApplyOpts |= ApplyFlags::DoesNotAwait;
77+
}
78+
7079
if (!Cloner.Inlining) {
7180
FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(AI.getCallee());
7281
if (FRI && FRI->getReferencedFunction() == AI.getFunction() &&
@@ -123,6 +132,10 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
123132
SubstitutionMap getSubstitutions() const {
124133
return Subs;
125134
}
135+
136+
ApplyOptions getApplyOptions() const {
137+
return ApplyOpts;
138+
}
126139
};
127140

128141
public:
@@ -214,7 +227,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
214227
getBuilder().createApply(getOpLocation(Inst->getLoc()),
215228
Helper.getCallee(), Helper.getSubstitutions(),
216229
Helper.getArguments(),
217-
Inst->getApplyOptions(),
230+
Helper.getApplyOptions(),
218231
GenericSpecializationInformation::create(
219232
Inst, getBuilder()));
220233
// Specialization can return noreturn applies that were not identified as
@@ -234,7 +247,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
234247
Helper.getSubstitutions(), Helper.getArguments(),
235248
getOpBasicBlock(Inst->getNormalBB()),
236249
getOpBasicBlock(Inst->getErrorBB()),
237-
Inst->getApplyOptions(),
250+
Helper.getApplyOptions(),
238251
GenericSpecializationInformation::create(
239252
Inst, getBuilder()));
240253
recordClonedInstruction(Inst, N);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-swift-frontend -emit-sil -enable-experimental-concurrency %s | %FileCheck %s
2+
3+
@_transparent
4+
func reasyncFunction(_ value: Optional<Int>, _ fn: () async throws -> Int) reasync rethrows -> Int {
5+
switch value {
6+
case .some(let x): return x
7+
case .none: return try await fn()
8+
}
9+
}
10+
11+
// CHECK-LABEL: sil hidden @$s26mandatory_inlining_reasync20callsReasyncFunctionSiyF : $@convention(thin) () -> Int {
12+
// CHECK: [[FN:%.*]] = function_ref @$s26mandatory_inlining_reasync20callsReasyncFunctionSiyFSiyXEfU_ : $@convention(thin) () -> Int
13+
// CHECK-NEXT: [[CONV:%.*]] = convert_function [[FN]] : $@convention(thin) () -> Int to $@convention(thin) @noescape () -> Int
14+
// CHECK-NEXT: [[THICK:%.*]] = thin_to_thick_function [[CONV]] : $@convention(thin) @noescape () -> Int to $@noescape @callee_guaranteed () -> Int
15+
// CHECK-NEXT: br bb1
16+
17+
// CHECK: bb1:
18+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[THICK]]() : $@noescape @callee_guaranteed () -> Int
19+
// CHECK-NEXT: br bb2
20+
21+
// CHECK: bb2:
22+
// CHECK-NEXT: return [[RESULT]] : $Int
23+
func callsReasyncFunction() -> Int {
24+
return reasyncFunction(nil, { return 321 } )
25+
}

0 commit comments

Comments
 (0)