Files
swift-mirror/test/SILOptimizer/issue-82155.swift
Ben Cohen 367b88e6cc Add regression test for redundant strong_retain/strong_release pair (#89473)
Locks in that closure specialization no longer leaves a redundant
strong_retain/strong_release pair around a non-escaping closure call
that captures a borrowed class reference. Fixed between Swift 6.3 and
6.4; test guards against future regression.

Resolves #82155
2026-05-28 06:33:32 -07:00

41 lines
1.5 KiB
Swift

// RUN: %target-swift-emit-sil -primary-file %s -O -module-name=test | %FileCheck %s
// Regression test for https://github.com/swiftlang/swift/issues/82155
//
// A non-escaping closure that captures a class reference should not introduce
// retain/release traffic at the call site after closure specialization, since
// the captured reference's lifetime is already covered by the caller's
// @guaranteed parameter.
public class Object { var count = 0 }
@inline(never)
func execute<T>(closure: () -> T) -> T {
closure()
}
// CHECK-LABEL: sil @$s4test7compare9reference5countSbAA6ObjectC_SitF : $@convention(thin) (@guaranteed Object, Int) -> Bool
// CHECK-NOT: strong_retain
// CHECK-NOT: strong_release
// CHECK: } // end sil function '$s4test7compare9reference5countSbAA6ObjectC_SitF'
public func compare(reference: Object, count: Int) -> Bool {
execute { reference.count == count }
}
@inline(never)
func executeVoid(closure: () -> Void) {
closure()
}
// Non-generic variant. The closure body must have an observable side effect so
// that dead-argument-removal does not strip the captured reference and erase
// the parameter we want to check.
//
// CHECK-LABEL: sil @$s4test11compareVoid9reference5countyAA6ObjectC_SitF : $@convention(thin) (@guaranteed Object, Int) -> ()
// CHECK-NOT: strong_retain
// CHECK-NOT: strong_release
// CHECK: } // end sil function '$s4test11compareVoid9reference5countyAA6ObjectC_SitF'
public func compareVoid(reference: Object, count: Int) {
executeVoid { reference.count = count }
}