Avatar
public func foo1() -> () -> Void { var x = 1 let closure: () -> Void = { [x] in print(x) } return closure } public func foo2() -> () -> Void { var x = 1 let closure: () -> Void do { let x = x closure = { () in print(x) } } return closure } これのSILを出力すると
8:58 AM
foo1 と foo2 はほぼ同じになる。
8:58 AM
// foo1() sil @$s4test4foo1yycyF : $@convention(thin) () -> @owned @callee_guaranteed () -> () { bb0: %0 = alloc_stack $Int, var, name "x" // users: %3, %10, %4 %1 = integer_literal $Builtin.Int64, 1 // user: %2 %2 = struct $Int (%1 : $Builtin.Int64) // users: %8, %6, %3 store %2 to %0 : $*Int // id: %3 %4 = begin_access [read] [static] %0 : $*Int // user: %5 end_access %4 : $*Int // id: %5 debug_value %2 : $Int, let, name "x" // id: %6 // function_ref closure #1 in foo1() %7 = function_ref @$s4test4foo1yycyFyycfU_ : $@convention(thin) (Int) -> () // user: %8 %8 = partial_apply [callee_guaranteed] %7(%2) : $@convention(thin) (Int) -> () // users: %11, %9 debug_value %8 : $@callee_guaranteed () -> (), let, name "closure" // id: %9 dealloc_stack %0 : $*Int // id: %10 return %8 : $@callee_guaranteed () -> () // id: %11 } // end sil function '$s4test4foo1yycyF'
8:58 AM
// foo2() sil @$s4test4foo2yycyF : $@convention(thin) () -> @owned @callee_guaranteed () -> () { bb0: %0 = alloc_stack $Int, var, name "x" // users: %3, %14, %5 %1 = integer_literal $Builtin.Int64, 1 // user: %2 %2 = struct $Int (%1 : $Builtin.Int64) // users: %9, %7, %3 store %2 to %0 : $*Int // id: %3 %4 = alloc_stack $@callee_guaranteed () -> (), let, name "closure" // users: %10, %12, %13 %5 = begin_access [read] [static] %0 : $*Int // user: %6 end_access %5 : $*Int // id: %6 debug_value %2 : $Int, let, name "x" // id: %7 // function_ref closure #1 in foo2() %8 = function_ref @$s4test4foo2yycyFyycfU_ : $@convention(thin) (Int) -> () // user: %9 %9 = partial_apply [callee_guaranteed] %8(%2) : $@convention(thin) (Int) -> () // users: %11, %15, %10 store %9 to %4 : $*@callee_guaranteed () -> () // id: %10 strong_retain %9 : $@callee_guaranteed () -> () // id: %11 destroy_addr %4 : $*@callee_guaranteed () -> () // id: %12 dealloc_stack %4 : $*@callee_guaranteed () -> () // id: %13 dealloc_stack %0 : $*Int // id: %14 return %9 : $@callee_guaranteed () -> () // id: %15 } // end sil function '$s4test4foo2yycyF'
9:00 AM
クロージャのタイプは @convention(thin) (Int) -> () で一緒であって、 それに partial_apply de