// RUN: %target-swift-emit-silgen -parse-as-library %s | %FileCheck %s // CHECK-LABEL: sil hidden [ossa] @$s15local_recursionAA_1yySi_SitF : $@convention(thin) (Int, Int) -> () { // CHECK: bb0([[X:%0]] : $Int, [[Y:%1]] : $Int): func local_recursion(_ x: Int, y: Int) { func self_recursive(_ a: Int) { self_recursive(x + a) } // Invoke local functions by passing all their captures. // CHECK: [[SELF_RECURSIVE_REF:%.*]] = function_ref [[SELF_RECURSIVE:@\$s15local_recursionAA_1yySi_SitF14self_recursiveL_yySiF]] // CHECK: apply [[SELF_RECURSIVE_REF]]([[X]], [[X]]) self_recursive(x) // CHECK: [[SELF_RECURSIVE_REF:%.*]] = function_ref [[SELF_RECURSIVE]] // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[SELF_RECURSIVE_REF]]([[X]]) // CHECK: [[MOVED_CLOSURE:%.*]] = move_value [lexical] [var_decl] [[CLOSURE]] // CHECK: [[BORROWED_CLOSURE:%.*]] = begin_borrow [[MOVED_CLOSURE]] // CHECK: [[CLOSURE_COPY:%.*]] = copy_value [[BORROWED_CLOSURE]] let sr = self_recursive // CHECK: [[B:%.*]] = begin_borrow [[CLOSURE_COPY]] // CHECK: apply [[B]]([[Y]]) // CHECK: end_borrow [[B]] // CHECK: destroy_value [[CLOSURE_COPY]] sr(y) func mutually_recursive_1(_ a: Int) { mutually_recursive_2(x + a) } func mutually_recursive_2(_ b: Int) { mutually_recursive_1(y + b) } // CHECK: [[MUTUALLY_RECURSIVE_REF:%.*]] = function_ref [[MUTUALLY_RECURSIVE_1:@\$s15local_recursionAA_1yySi_SitF20mutually_recursive_1L_yySiF]] // CHECK: apply [[MUTUALLY_RECURSIVE_REF]]([[X]], [[Y]], [[X]]) mutually_recursive_1(x) // CHECK: [[MUTUALLY_RECURSIVE_REF:%.*]] = function_ref [[MUTUALLY_RECURSIVE_1]] _ = mutually_recursive_1 func transitive_capture_1(_ a: Int) -> Int { return x + a } func transitive_capture_2(_ b: Int) -> Int { return transitive_capture_1(y + b) } // CHECK: [[TRANS_CAPTURE_REF:%.*]] = function_ref [[TRANS_CAPTURE:@\$s15local_recursionAA_1yySi_SitF20transitive_capture_2L_yS2iF]] // CHECK: apply [[TRANS_CAPTURE_REF]]([[X]], [[X]], [[Y]]) transitive_capture_2(x) // CHECK: [[TRANS_CAPTURE_REF:%.*]] = function_ref [[TRANS_CAPTURE]] // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[TRANS_CAPTURE_REF]]([[X]], [[Y]]) // CHECK: [[MOVED_CLOSURE:%.*]] = move_value [lexical] [var_decl] [[CLOSURE]] // CHECK: [[BORROWED_CLOSURE:%.*]] = begin_borrow [[MOVED_CLOSURE]] // CHECK: [[CLOSURE_COPY:%.*]] = copy_value [[BORROWED_CLOSURE]] let tc = transitive_capture_2 // CHECK: [[B:%.*]] = begin_borrow [[CLOSURE_COPY]] // CHECK: apply [[B]]([[X]]) // CHECK: end_borrow [[B]] // CHECK: destroy_value [[CLOSURE_COPY]] tc(x) // CHECK: [[CLOSURE_REF:%.*]] = function_ref @$s15local_recursionAA_1yySi_SitFySiXEfU_ // CHECK: apply [[CLOSURE_REF]]([[X]], [[X]], [[Y]]) let _: Void = { self_recursive($0) transitive_capture_2($0) }(x) // CHECK: [[CLOSURE_REF:%.*]] = function_ref @$s15local_recursionAA_1yySi_SitFySicfU0_ // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_REF]]([[X]], [[Y]]) // CHECK: [[MOVED_CLOSURE:%.*]] = move_value [lexical] [var_decl] [[CLOSURE]] // CHECK: [[BORROWED_CLOSURE:%.*]] = begin_borrow [[MOVED_CLOSURE]] // CHECK: [[CLOSURE_COPY:%.*]] = copy_value [[BORROWED_CLOSURE]] // CHECK: [[B:%.*]] = begin_borrow [[CLOSURE_COPY]] // CHECK: apply [[B]]([[X]]) // CHECK: end_borrow [[B]] // CHECK: destroy_value [[CLOSURE_COPY]] let f: (Int) -> () = { self_recursive($0) transitive_capture_2($0) } f(x) } // CHECK: sil private [ossa] [[SELF_RECURSIVE]] : // CHECK: bb0([[A:%0]] : $Int, [[X:%1]] : @closureCapture $Int): // CHECK: [[SELF_REF:%.*]] = function_ref [[SELF_RECURSIVE]] : // CHECK: apply [[SELF_REF]]({{.*}}, [[X]]) // CHECK: sil private [ossa] [[MUTUALLY_RECURSIVE_1]] // CHECK: bb0([[A:%0]] : $Int, [[Y:%1]] : @closureCapture $Int, [[X:%2]] : @closureCapture $Int): // CHECK: [[MUTUALLY_RECURSIVE_REF:%.*]] = function_ref [[MUTUALLY_RECURSIVE_2:@\$s15local_recursionAA_1yySi_SitF20mutually_recursive_2L_yySiF]] // CHECK: apply [[MUTUALLY_RECURSIVE_REF]]({{.*}}, [[X]], [[Y]]) // CHECK: sil private [ossa] [[MUTUALLY_RECURSIVE_2]] // CHECK: bb0([[B:%0]] : $Int, [[X:%1]] : @closureCapture $Int, [[Y:%2]] : @closureCapture $Int): // CHECK: [[MUTUALLY_RECURSIVE_REF:%.*]] = function_ref [[MUTUALLY_RECURSIVE_1]] // CHECK: apply [[MUTUALLY_RECURSIVE_REF]]({{.*}}, [[Y]], [[X]]) // CHECK: sil private [ossa] [[TRANS_CAPTURE_1:@\$s15local_recursionAA_1yySi_SitF20transitive_capture_1L_yS2iF]] // CHECK: bb0([[A:%0]] : $Int, [[X:%1]] : @closureCapture $Int): // CHECK: sil private [ossa] [[TRANS_CAPTURE]] // CHECK: bb0([[B:%0]] : $Int, [[X:%1]] : @closureCapture $Int, [[Y:%2]] : @closureCapture $Int): // CHECK: [[TRANS_CAPTURE_1_REF:%.*]] = function_ref [[TRANS_CAPTURE_1]] // CHECK: apply [[TRANS_CAPTURE_1_REF]]({{.*}}, [[X]]) func plus(_ x: T, _ y: T) -> T { return x } func toggle(_ x: T, _ y: U) -> U { return y } func generic_local_recursion(_ x: T, y: U) { func self_recursive(_ a: T) { self_recursive(plus(x, a)) } self_recursive(x) _ = self_recursive func transitive_capture_1(_ a: T) -> U { return toggle(a, y) } func transitive_capture_2(_ b: U) -> U { return transitive_capture_1(toggle(b, x)) } transitive_capture_2(y) _ = transitive_capture_2 func no_captures() {} no_captures() _ = no_captures func transitive_no_captures() { no_captures() } transitive_no_captures() _ = transitive_no_captures } func local_properties(_ x: Int, y: Int) -> Int { var self_recursive: Int { return x + self_recursive } var transitive_capture_1: Int { return x } var transitive_capture_2: Int { return transitive_capture_1 + y } func transitive_capture_fn() -> Int { return transitive_capture_2 } return self_recursive + transitive_capture_fn() }