File: variadic-generic-reabstract-tuple-arg.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (122 lines) | stat: -rw-r--r-- 8,232 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// RUN: %target-swift-emit-silgen -disable-availability-checking %s | %FileCheck %s

func takeEscapingFunction<each Input, Output>(function: @escaping ((repeat each Input)) -> Output) {}
func returnFunction<each Input, Output>(args: (repeat each Input).Type, result: Output.Type) -> (_: (repeat each Input)) -> Output {}

// Issue #69028: Vanishing tuple in a reabstraction into a more abstract context
func catFact(num: Int) -> String { "there are more than 10 cats" }
func test0() {
  takeEscapingFunction(function: catFact)
}
// CHECK-LABEL: sil hidden [ossa] @$s4main5test0yyF :
// CHECK:         [[THUNK:%.*]] = function_ref @$sSiSSIegyo_Si_QSiSSIegpr_TR : $@convention(thin) (@pack_guaranteed Pack{Int}, @guaranteed @callee_guaranteed (Int) -> @owned String) -> @out String
// CHECK-NEXT:    partial_apply [callee_guaranteed] [[THUNK]]

// CHECK-LABEL: sil shared {{.*}} @$sSiSSIegyo_Si_QSiSSIegpr_TR : $@convention(thin) (@pack_guaranteed Pack{Int}, @guaranteed @callee_guaranteed (Int) -> @owned String) -> @out String {
// CHECK:       bb0(%0 : $*String, %1 : $*Pack{Int}, %2 : @guaranteed $@callee_guaranteed (Int) -> @owned String):
// CHECK-NEXT:    [[INDEX:%.*]] = scalar_pack_index 0 of $Pack{Int}
// CHECK-NEXT:    [[ARG_ADDR:%.*]] = pack_element_get [[INDEX]] of %1 : $*Pack{Int} as $*Int
// CHECK-NEXT:    [[ARG:%.*]] = load [trivial] [[ARG_ADDR]] : $*Int
// CHECK-NEXT:    [[RESULT:%.*]] = apply %2([[ARG]]) : $@callee_guaranteed (Int) -> @owned String
// CHECK-NEXT:    store [[RESULT]] to [init] %0 : $*String
// CHECK-NEXT:    [[RESULT:%.*]] = tuple ()
// CHECK-NEXT:    return [[RESULT]] : $()
// CHECK-NEXT:  }

// Vanishing tuple in a reabstraction out of a more abstract context
func test1() {
  _ = returnFunction(args: String.self, result: [String].self)
}
// CHECK-LABEL: sil hidden [ossa] @$s4main5test1yyF :
// CHECK:         [[THUNK:%.*]] = function_ref @$sSS_QSiSaySSGIegpr_SSAAIeggo_TR : $@convention(thin) (@guaranteed String, @guaranteed @callee_guaranteed (@pack_guaranteed Pack{String}) -> @out Array<String>) -> @owned Array<String>
// CHECK-NEXT:    partial_apply [callee_guaranteed] [[THUNK]]

// CHECK-LABEL: sil shared {{.*}} @$sSS_QSiSaySSGIegpr_SSAAIeggo_TR : $@convention(thin) (@guaranteed String, @guaranteed @callee_guaranteed (@pack_guaranteed Pack{String}) -> @out Array<String>) -> @owned Array<String> {
// CHECK:       bb0(%0 : @guaranteed $String, %1 : @guaranteed $@callee_guaranteed (@pack_guaranteed Pack{String}) -> @out Array<String>):
// CHECK-NEXT:    [[PACK:%.*]] = alloc_pack $Pack{String}
// CHECK-NEXT:    [[ARG_TEMP:%.*]] = alloc_stack $String
//   It'd be nice to avoid this unnecessary copy.
// CHECK-NEXT:    [[ARG_TEMP_BORROW:%.*]] = store_borrow %0 to [[ARG_TEMP]]
// CHECK-NEXT:    [[INDEX:%.*]] = scalar_pack_index 0 of $Pack{String}
// CHECK-NEXT:    pack_element_set [[ARG_TEMP_BORROW]] : $*String into [[INDEX]] of [[PACK]] : $*Pack{String}
// CHECK-NEXT:    [[RESULT_TEMP:%.*]] = alloc_stack $Array<String>
// CHECK-NEXT:    apply %1([[RESULT_TEMP]], [[PACK]]) : $@callee_guaranteed (@pack_guaranteed Pack{String}) -> @out Array<String>
// CHECK-NEXT:    [[RESULT:%.*]] = load [take] [[RESULT_TEMP]] : $*Array<String>
// CHECK-NEXT:    dealloc_stack [[RESULT_TEMP]] : $*Array<String>
// CHECK-NEXT:    end_borrow [[ARG_TEMP_BORROW]]
// CHECK-NEXT:    dealloc_stack [[ARG_TEMP]] : $*String
// CHECK-NEXT:    dealloc_pack [[PACK]] : $*Pack{String}
// CHECK-NEXT:    return [[RESULT]] : $Array<String>
// CHECK-NEXT:  }

// A non-vanishing tuple in a reabstraction into a more abstract context
func lionFact(label: (String, Int)) -> String { "all lions are cats" }
func test2() {
  takeEscapingFunction(function: lionFact)
}
// CHECK-LABEL: sil hidden [ossa] @$s4main5test2yyF :
// CHECK:         [[THUNK:%.*]] = function_ref @$sSSSiSSIeggyo_SS_SiQSiSSIegpr_TR : $@convention(thin) (@pack_guaranteed Pack{String, Int}, @guaranteed @callee_guaranteed (@guaranteed String, Int) -> @owned String) -> @out String
// CHECK-NEXT:    partial_apply [callee_guaranteed] [[THUNK]]

// CHECK-LABEL: sil shared {{.*}} @$sSSSiSSIeggyo_SS_SiQSiSSIegpr_TR : $@convention(thin) (@pack_guaranteed Pack{String, Int}, @guaranteed @callee_guaranteed (@guaranteed String, Int) -> @owned String) -> @out String {
// CHECK:       bb0(%0 : $*String, %1 : $*Pack{String, Int}, %2 : @guaranteed $@callee_guaranteed (@guaranteed String, Int) -> @owned String):
// CHECK-NEXT:    [[ARG0_INDEX:%.*]] = scalar_pack_index 0 of $Pack{String, Int}
// CHECK-NEXT:    [[ARG0_ADDR:%.*]] = pack_element_get [[ARG0_INDEX]] of %1 : $*Pack{String, Int} as $*String
// CHECK-NEXT:    [[ARG0:%.*]] = load_borrow [[ARG0_ADDR]] : $*String
// CHECK-NEXT:    [[ARG1_INDEX:%.*]] = scalar_pack_index 1 of $Pack{String, Int}
// CHECK-NEXT:    [[ARG1_ADDR:%.*]] = pack_element_get [[ARG1_INDEX]] of %1 : $*Pack{String, Int} as $*Int
// CHECK-NEXT:    [[ARG1:%.*]] = load [trivial] [[ARG1_ADDR]] : $*Int
// CHECK-NEXT:    [[RESULT:%.*]] = apply %2([[ARG0]], [[ARG1]]) : $@callee_guaranteed (@guaranteed String, Int) -> @owned String
// CHECK-NEXT:    store [[RESULT]] to [init] %0 : $*String
// CHECK-NEXT:    [[RESULT:%.*]] = tuple ()
// CHECK-NEXT:    end_borrow [[ARG0]] : $String
// CHECK-NEXT:    return [[RESULT]] : $()
// CHECK-NEXT:  }

struct Args<each T> {
  static func take(function: @escaping (_: (repeat each T)) -> ()) {}
}

#if false
// For some reason, this doesn't type-check
func test3(function: @escaping (_: (Int, String)?) -> ()) {
  Args<Int, String>.take(function: function)
}
#endif

func test4<each T>(function: @escaping (_: Any) -> (), type: (repeat each T).Type) {
  Args<repeat each T>.take(function: function)
}
// CHECK-LABEL: sil hidden [ossa] @$s4main5test48function4typeyyypc_xxQp_tmtRvzlF :
// CHECK:         [[THUNK:%.*]] = function_ref @$sypIegn_xxQp_QSiIegp_RvzlTR : $@convention(thin) <each τ_0_0> (@pack_guaranteed Pack{repeat each τ_0_0}, @guaranteed @callee_guaranteed (@in_guaranteed Any) -> ()) -> ()
// CHECK-NEXT:    partial_apply [callee_guaranteed] [[THUNK]]

// CHECK-LABEL: sil shared {{.*}} @$sypIegn_xxQp_QSiIegp_RvzlTR : $@convention(thin) <each T> (@pack_guaranteed Pack{repeat each T}, @guaranteed @callee_guaranteed (@in_guaranteed Any) -> ()) -> () {
// CHECK:       bb0(%0 : $*Pack{repeat each T}, %1 : @guaranteed $@callee_guaranteed (@in_guaranteed Any) -> ()):
//   - Set up for emitting into a temporary Any object.
// CHECK-NEXT:    [[ANY_TEMP:%.*]] = alloc_stack $Any
// CHECK-NEXT:    [[PAYLOAD_ADDR:%.*]] = init_existential_addr [[ANY_TEMP]] : $*Any, $(repeat each T)
//   - Loop over the pack and copy the elements into the Any.
// CHECK-NEXT:    [[ZERO:%.*]] = integer_literal $Builtin.Word, 0
// CHECK-NEXT:    [[ONE:%.*]] = integer_literal $Builtin.Word, 1
// CHECK-NEXT:    [[LEN:%.*]] = pack_length $Pack{repeat each T}
// CHECK-NEXT:    br bb1([[ZERO]] : $Builtin.Word)
// CHECK:       bb1([[IDX:%.*]] : $Builtin.Word)
// CHECK-NEXT:    [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1
// CHECK-NEXT:     cond_br [[IDX_EQ_LEN]], bb3, bb2
// CHECK:       bb2:
// CHECK-NEXT:    [[EXPANSION_INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat each T}
// CHECK-NEXT:    open_pack_element [[EXPANSION_INDEX]] of <each T> at <Pack{repeat each T}>, shape $each T, uuid [[UUID:".*"]]
// CHECK-NEXT:    [[SRC_ELT_ADDR:%.*]] = pack_element_get [[EXPANSION_INDEX]] of %0 : $*Pack{repeat each T} as $*@pack_element([[UUID]]) each T
// CHECK-NEXT:    [[DEST_ELT_ADDR:%.*]] = tuple_pack_element_addr [[EXPANSION_INDEX]] of [[PAYLOAD_ADDR]] : $*(repeat each T) as $*@pack_element([[UUID]]) each T
// CHECK-NEXT:    copy_addr [[SRC_ELT_ADDR]] to [init] [[DEST_ELT_ADDR]] : $*@pack_element([[UUID]]) each T
// CHECK-NEXT:    [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word
// CHECK-NEXT:    br bb1([[NEXT_IDX]] : $Builtin.Word)
// CHECK:       bb3:
//   - Call the thunked function.
// CHECK-NEXT:    apply %1([[ANY_TEMP]])
//   - Epilogue.
// CHECK-NEXT:    [[VOID:%.*]] = tuple ()
// CHECK-NEXT:    destroy_addr [[ANY_TEMP]] : $*Any
// CHECK-NEXT:    dealloc_stack [[ANY_TEMP]] : $*Any
// CHECK-NEXT:    return [[VOID]] : $()