mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Changes in https://github.com/swiftlang/swift/pull/81370 addressed a number of issues with isolated default argument handling. However, there seemed to still be a problem when dealing with isolated default arguments of instance/static methods under the following conditions: - The method contained an isolated default parameter - The method contained a defaulted parameter that expanded to 0 or >1 values - Said parameter was followed by another defaulted parameter The attempted fix here was to adjust the isolated default argument iteration bookkeeping.
227 lines
8.8 KiB
Swift
227 lines
8.8 KiB
Swift
// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types -module-name test -Xllvm -sil-full-demangle -swift-version 6 %s | %FileCheck %s
|
|
|
|
// We weren't adjusting offsets around isolated default arguments
|
|
// properly, and it broke when presented with a non-isolated or
|
|
// non-defaulted argument between two isolated default arguments.
|
|
|
|
@MainActor
|
|
func main_actor_int_x() -> Int {
|
|
return 0
|
|
}
|
|
|
|
@MainActor
|
|
func main_actor_int_y() -> Int {
|
|
return 0
|
|
}
|
|
|
|
@MainActor
|
|
func main_actor_int_z() -> Int {
|
|
return 0
|
|
}
|
|
|
|
@MainActor
|
|
func main_actor_void() -> () {
|
|
}
|
|
|
|
@MainActor
|
|
func main_actor_int_pair() -> (Int, Int) {
|
|
return (0,0)
|
|
}
|
|
|
|
func make_int(isolated isolation: (any Actor)? = #isolation) -> Int {
|
|
return 0
|
|
}
|
|
|
|
// This test breaks because the intermediate argument is `nil`, which
|
|
// we treat as non-isolated.
|
|
@MainActor
|
|
func nonIsolatedDefaultArg(x: Int = main_actor_int_x(),
|
|
y: Int? = nil,
|
|
z: Int = main_actor_int_z()) {}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s4test0A21NonIsolatedDefaultArgyyYaF :
|
|
// CHECK: [[ARG1:%.*]] = enum $Optional<Int>, #Optional.none
|
|
// CHECK: hop_to_executor {{%.*}} : $MainActor
|
|
// CHECK-NEXT: // function_ref default argument 0 of
|
|
// CHECK-NEXT: [[ARG0FN:%.*]] = function_ref @$s4test21nonIsolatedDefaultArg1x1y1zySi_SiSgSitFfA_
|
|
// CHECK-NEXT: [[ARG0:%.*]] = apply [[ARG0FN]]()
|
|
// CHECK-NEXT: // function_ref default argument 2 of
|
|
// CHECK-NEXT: [[ARG2FN:%.*]] = function_ref @$s4test21nonIsolatedDefaultArg1x1y1zySi_SiSgSitFfA1_
|
|
// CHECK-NEXT: [[ARG2:%.*]] = apply [[ARG2FN]]()
|
|
// CHECK-NEXT: // function_ref test.nonIsolatedDefaultArg
|
|
// CHECK-NEXT: [[FN:%.*]] = function_ref @$s4test21nonIsolatedDefaultArg1x1y1zySi_SiSgSitF :
|
|
// CHECK: apply [[FN]]([[ARG0]], [[ARG1]], [[ARG2]])
|
|
func testNonIsolatedDefaultArg() async {
|
|
await nonIsolatedDefaultArg()
|
|
}
|
|
|
|
// This test breaks because the intermediate argument is non-defaulted
|
|
// and so gets evaluated in the non-delayed argument pass.
|
|
@MainActor
|
|
func isolatedDefaultArgs(x: Int = main_actor_int_x(),
|
|
y: Int = main_actor_int_y(),
|
|
z: Int = main_actor_int_z()) {}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s4test0A13NonDefaultArgyyYaF :
|
|
// CHECK: [[LITERAL_FN:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC :
|
|
// CHECK-NEXT: [[ARG1:%.*]] = apply [[LITERAL_FN]](
|
|
// CHECK: hop_to_executor {{%.*}} : $MainActor
|
|
// CHECK-NEXT: // function_ref default argument 0 of
|
|
// CHECK-NEXT: [[ARG0FN:%.*]] = function_ref @$s4test19isolatedDefaultArgs1x1y1zySi_S2itFfA_
|
|
// CHECK-NEXT: [[ARG0:%.*]] = apply [[ARG0FN]]()
|
|
// CHECK-NEXT: // function_ref default argument 2 of
|
|
// CHECK-NEXT: [[ARG2FN:%.*]] = function_ref @$s4test19isolatedDefaultArgs1x1y1zySi_S2itFfA1_
|
|
// CHECK-NEXT: [[ARG2:%.*]] = apply [[ARG2FN]]()
|
|
// CHECK-NEXT: // function_ref test.isolatedDefaultArgs
|
|
// CHECK-NEXT: [[FN:%.*]] = function_ref @$s4test19isolatedDefaultArgs1x1y1zySi_S2itF :
|
|
// CHECK: apply [[FN]]([[ARG0]], [[ARG1]], [[ARG2]])
|
|
func testNonDefaultArg() async {
|
|
await isolatedDefaultArgs(y: 0)
|
|
}
|
|
|
|
// Exercise our handling of isolated default arguments that expand to
|
|
// empty or multiple arguments.
|
|
@MainActor
|
|
func voidIsolatedDefaultArg(x: () = main_actor_void(),
|
|
y: Int = main_actor_int_y(),
|
|
z: Int = main_actor_int_z()) {}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s4test0A22VoidIsolatedDefaultArgyyYaF :
|
|
// CHECK: [[LITERAL_FN:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC :
|
|
// CHECK-NEXT: [[ARG1:%.*]] = apply [[LITERAL_FN]](
|
|
// CHECK: hop_to_executor {{%.*}} : $MainActor
|
|
// CHECK-NEXT: // function_ref default argument 0 of
|
|
// CHECK-NEXT: [[ARG0FN:%.*]] = function_ref @$s4test22voidIsolatedDefaultArg1x1y1zyyt_S2itFfA_
|
|
// CHECK-NEXT: [[ARG0:%.*]] = apply [[ARG0FN]]()
|
|
// CHECK-NEXT: // function_ref default argument 2 of
|
|
// CHECK-NEXT: [[ARG2FN:%.*]] = function_ref @$s4test22voidIsolatedDefaultArg1x1y1zyyt_S2itFfA1_
|
|
// CHECK-NEXT: [[ARG2:%.*]] = apply [[ARG2FN]]()
|
|
// CHECK-NEXT: // function_ref test.voidIsolatedDefaultArg
|
|
// CHECK-NEXT: [[FN:%.*]] = function_ref @$s4test22voidIsolatedDefaultArg1x1y1zyyt_S2itF :
|
|
// CHECK: apply [[FN]]([[ARG1]], [[ARG2]])
|
|
func testVoidIsolatedDefaultArg() async {
|
|
await voidIsolatedDefaultArg(y: 0)
|
|
}
|
|
|
|
@MainActor
|
|
func tupleIsolatedDefaultArg(x: (Int,Int) = main_actor_int_pair(),
|
|
y: Int = main_actor_int_y(),
|
|
z: Int = main_actor_int_z()) {}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s4test0A23TupleIsolatedDefaultArgyyYaF :
|
|
// CHECK: [[LITERAL_FN:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC :
|
|
// CHECK-NEXT: [[ARG1:%.*]] = apply [[LITERAL_FN]](
|
|
// CHECK: hop_to_executor {{%.*}} : $MainActor
|
|
// CHECK-NEXT: // function_ref default argument 0 of
|
|
// CHECK-NEXT: [[ARG0FN:%.*]] = function_ref @$s4test23tupleIsolatedDefaultArg1x1y1zySi_Sit_S2itFfA_
|
|
// CHECK-NEXT: [[ARG0:%.*]] = apply [[ARG0FN]]()
|
|
// CHECK-NEXT: ([[ARG0_0:%.*]], [[ARG0_1:%.*]]) = destructure_tuple [[ARG0]] : $(Int, Int)
|
|
// CHECK-NEXT: // function_ref default argument 2 of
|
|
// CHECK-NEXT: [[ARG2FN:%.*]] = function_ref @$s4test23tupleIsolatedDefaultArg1x1y1zySi_Sit_S2itFfA1_
|
|
// CHECK-NEXT: [[ARG2:%.*]] = apply [[ARG2FN]]()
|
|
// CHECK-NEXT: // function_ref test.tupleIsolatedDefaultArg
|
|
// CHECK-NEXT: [[FN:%.*]] = function_ref @$s4test23tupleIsolatedDefaultArg1x1y1zySi_Sit_S2itF :
|
|
// CHECK: apply [[FN]]([[ARG0_0]], [[ARG0_1]], [[ARG1]], [[ARG2]])
|
|
func testTupleIsolatedDefaultArg() async {
|
|
await tupleIsolatedDefaultArg(y: 0)
|
|
}
|
|
|
|
// When a function is caller-isolated, its default argument generators
|
|
// should probably also be caller-isolated and forward their isolation
|
|
// properly when #isolation is used. Currently, however, that's not what
|
|
// we're doing, so test for the current behavior.
|
|
|
|
nonisolated(nonsending)
|
|
func callerIsolatedDefaultArg(x: Int = make_int()) async {}
|
|
|
|
@MainActor
|
|
func useCallerIsolatedDefaultArg() async {
|
|
await callerIsolatedDefaultArg()
|
|
}
|
|
|
|
// Check that the default argument generator isn't caller-isolated.
|
|
// CHECK-LABEL: // default argument 0 of test.callerIsolatedDefaultArg
|
|
// CHECK-NEXT: // Isolation: unspecified
|
|
// CHECK-NEXT: sil hidden [ossa] @$s4test24callerIsolatedDefaultArg1xySi_tYaFfA_ :
|
|
// CHECK: bb0:
|
|
// Check that we provide a nil isolation for #isolation
|
|
// CHECK-NEXT: [[NIL_ISOLATION:%.*]] = enum $Optional<any Actor>, #Optional.none
|
|
// CHECK-NEXT: // function_ref test.make_int
|
|
// CHECK-NEXT: [[FN:%.*]] = function_ref @$s4test8make_int8isolatedSiScA_pSg_tF :
|
|
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]([[NIL_ISOLATION]])
|
|
// CHECK-NEXT: return [[RESULT]]
|
|
|
|
// Check that we pass the right isolation to the generator.
|
|
// CHECK-LABEL: sil hidden [ossa] @$s4test27useCallerIsolatedDefaultArgyyYaF :
|
|
// Get the main actor reference.
|
|
// CHECK: [[GET_MAIN_ACTOR:%.*]] = function_ref @$sScM6sharedScMvgZ :
|
|
// CHECK-NEXT: [[T0:%.*]] = apply [[GET_MAIN_ACTOR]](
|
|
// CHECK-NEXT: [[MAIN_ACTOR:%.*]] = begin_borrow [[T0]]
|
|
// Call the accessor.
|
|
// CHECK: // function_ref default argument 0 of
|
|
// CHECK-NEXT: [[GEN:%.*]] = function_ref @$s4test24callerIsolatedDefaultArg1xySi_tYaFfA_ :
|
|
// CHECK-NEXT: [[ARG:%.*]] = apply [[GEN]]()
|
|
|
|
// The following tests failed due to a book-keeping error when processing delayed
|
|
// isolated arguments in methods with:
|
|
//
|
|
// - a `self` parameter
|
|
// - delayed arguments that expanded to zero or greater than one value
|
|
// - a subsequent delayed argument
|
|
//
|
|
// https://github.com/swiftlang/swift/issues/84647
|
|
|
|
@MainActor
|
|
enum E {
|
|
static func tupleIsolatedDefaultArgStatic(
|
|
_: Int,
|
|
x: Int = main_actor_int_x(),
|
|
// need not be isolated defaults
|
|
tup: (Int, Int) = (1, 2),
|
|
i: Int = 0
|
|
) {}
|
|
|
|
static func voidIsolatedDefaultArgStatic(
|
|
_: Int,
|
|
v: Void = main_actor_void(),
|
|
// need not be isolated defaults
|
|
tup: (Int, Int) = (1, 2),
|
|
i: Int = 0
|
|
) {}
|
|
}
|
|
|
|
func testTupleIsolatedDefaultArgStatic() async {
|
|
await E.tupleIsolatedDefaultArgStatic(0)
|
|
}
|
|
|
|
func testVoidIsolatedDefaultArgStatic() async {
|
|
await E.voidIsolatedDefaultArgStatic(0)
|
|
}
|
|
|
|
@MainActor
|
|
final class Klazz {
|
|
func tupleIsolatedDefaultArgInstanceMethod(
|
|
_: Int,
|
|
x: Int = main_actor_int_x(),
|
|
// need not be isolated defaults
|
|
tup: (Int, Int) = (1, 2),
|
|
i: Int = 0
|
|
) {}
|
|
|
|
func voidIsolatedDefaultArgInstanceMethod(
|
|
_: Int,
|
|
v: Void = main_actor_void(),
|
|
// need not be isolated defaults
|
|
tup: (Int, Int) = (1, 2),
|
|
i: Int = 0
|
|
) {}
|
|
}
|
|
|
|
func testTupleIsolatedDefaultArgInstanceMethod(_ klazz: Klazz) async {
|
|
await klazz.tupleIsolatedDefaultArgInstanceMethod(0)
|
|
}
|
|
|
|
func testVoidIsolatedDefaultArgInstanceMethod(_ klazz: Klazz) async {
|
|
await klazz.voidIsolatedDefaultArgInstanceMethod(0)
|
|
}
|