From 6988b03c133f4107e73713aaad7753359bee922e Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Tue, 21 Oct 2025 08:09:55 +0200 Subject: [PATCH] ClosureSpecialization: don't crash for recursive functions Don't support self-recursive functions because that would result in mapping troubles when cloning. --- .../ClosureSpecialization.swift | 5 +++- test/SILOptimizer/closure_specialization.sil | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ClosureSpecialization.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ClosureSpecialization.swift index aabfc62369030..b57244b98737a 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ClosureSpecialization.swift +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ClosureSpecialization.swift @@ -242,7 +242,10 @@ private func isCalleeSpecializable(of apply: ApplySite) -> Bool { // might no longer have 'self' as the last parameter. // // TODO: Keep the self argument the last when appending arguments. - !callee.mayBindDynamicSelf + !callee.mayBindDynamicSelf, + + // Don't support self-recursive functions because that would result in duplicate mapping of values when cloning. + callee != apply.parentFunction { return true } diff --git a/test/SILOptimizer/closure_specialization.sil b/test/SILOptimizer/closure_specialization.sil index 5c3d776b2d01d..7ea1372b7edb3 100644 --- a/test/SILOptimizer/closure_specialization.sil +++ b/test/SILOptimizer/closure_specialization.sil @@ -947,3 +947,28 @@ bb0(%nc : @owned $NC): %11 = tuple () return %11 : $() } + +sil @closure_with_closure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () + +// Just make sure the pass is not crashing. +sil [ossa] @test_recursion : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () { +bb0(%0 : @guaranteed $@callee_guaranteed () -> ()): + %2 = apply %0() : $@callee_guaranteed () -> () + cond_br undef, bb1, bb2 + +bb1: + %5 = function_ref @closure_with_closure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () + %6 = copy_value %0 + %7 = partial_apply [callee_guaranteed] %5(%6) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () + %8 = function_ref @test_recursion : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () + %9 = apply %8(%7) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () + destroy_value %7 + br bb3 + +bb2: + br bb3 + +bb3: + %13 = tuple () + return %13 +}