Skip to content

Commit f36668e

Browse files
committed
SILGen: Include more effects in function_conversion peephole.
Sometimes we emit a closure literal with escaping/nonthrowing/nonasync type into a context that wants a nonescaping/throwing/async function, and it ends up wrapped in a conversion. We can look through any of these and emit the closure literal directly with those effects.
1 parent d06f7b1 commit f36668e

File tree

3 files changed

+28
-10
lines changed

3 files changed

+28
-10
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,11 +1754,26 @@ static bool canPeepholeLiteralClosureConversion(Type literalType,
17541754
return true;
17551755
}
17561756

1757-
// Does the conversion only add `throws`?
1758-
if (literalFnType->isEqual(convertedFnType->getWithoutThrowing())) {
1757+
// Are the types equivalent aside from effects (throws) or coeffects
1758+
// (escaping)? Then we should emit the literal as having the destination type
1759+
// (co)effects, even if it doesn't exercise them.
1760+
//
1761+
// TODO: We could also in principle let `async` through here, but that
1762+
// interferes with the implementation of `reasync`.
1763+
auto literalWithoutEffects = literalFnType->getExtInfo().intoBuilder()
1764+
.withThrows(false)
1765+
.withNoEscape(false)
1766+
.build();
1767+
1768+
auto convertedWithoutEffects = convertedFnType->getExtInfo().intoBuilder()
1769+
.withThrows(false)
1770+
.withNoEscape(false)
1771+
.build();
1772+
if (literalFnType->withExtInfo(literalWithoutEffects)
1773+
->isEqual(convertedFnType->withExtInfo(convertedWithoutEffects))) {
17591774
return true;
17601775
}
1761-
1776+
17621777
return false;
17631778
}
17641779

test/SILGen/closure_literal_reabstraction.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,11 @@ func reabstractCaptureListExprArgument() {
2424
func reabstractKeyPathFunctionArgument() {
2525
gen(f: \Butt.x)
2626
}
27+
28+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractStaticMemberRef
29+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
30+
// CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[CLOSURE_FN]]
31+
// CHECK: apply {{.*}}<Int, Butt>([[CLOSURE]])
32+
func reabstractStaticMemberRef() {
33+
gen(f: Butt.init)
34+
}

test/SILOptimizer/closure_lifetime_fixup.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,10 @@ public func dontCrash<In, Out>(test: Bool, body: @escaping ((In) -> Out, In) ->
9595
}
9696

9797
// CHECK-LABEL: sil @$s22closure_lifetime_fixup28to_stack_of_convert_function1pySvSg_tF
98-
// CHECK: [[FN:%.*]] = function_ref @$s22closure_lifetime_fixup28to_stack_of_convert_function1pySvSg_tFSSSvcfu_ : $@convention(thin) (UnsafeMutableRawPointer) -> @owned String
98+
// CHECK: [[FN:%.*]] = function_ref @$s22closure_lifetime_fixup28to_stack_of_convert_function1pySvSg_tFSSSvcfu_ :
9999
// CHECK: [[PA:%.*]] = thin_to_thick_function [[FN]]
100-
// CHECK: [[CVT:%.*]] = convert_function [[PA]]
101-
// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[CVT]]
102-
// CHECK: [[REABSTRACT:%.*]] = function_ref @$sSvSSs5Error_pIgyozo_SvSSsAA_pIegnrzo_TR
103-
// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[REABSTRACT]]([[CVT2]])
104-
// CHECK: [[CF2:%.*]] = convert_function [[PA2]]
105100
// CHECK: [[MAP:%.*]] = function_ref @$sSq3mapyqd__Sgqd__xKXEKlF
106-
// CHECK: try_apply [[MAP]]<UnsafeMutableRawPointer, String>({{.*}}, [[CF2]], {{.*}})
101+
// CHECK: try_apply [[MAP]]<UnsafeMutableRawPointer, String>({{.*}}, [[PA]], {{.*}})
107102
public func to_stack_of_convert_function(p: UnsafeMutableRawPointer?) {
108103
_ = p.map(String.init(describing:))
109104
}

0 commit comments

Comments
 (0)