Skip to content

Commit 3bdee8c

Browse files
committed
Fix an ownership bug when splitting an opaque tuple value into
a pack expansion.
1 parent ce9013a commit 3bdee8c

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

lib/SILGen/SILGenDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ static void copyOrInitPackExpansionInto(SILGenFunction &SGF,
106106
// element value, that's fine, we'll just destroy it as part of
107107
// leaving the iteration.
108108
eltInit->copyOrInitValueInto(SGF, loc, eltMV, isInit);
109+
eltInit->finishInitialization(SGF);
109110

110111
// Deactivate the tail cleanup before continuing the loop.
111112
if (tailCleanup.isValid())

test/SILGen/variadic-generic-results.swift

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,60 @@ func callCopyAndBind<each T>(args: repeat each T) {
212212
sequence()
213213
}
214214

215+
struct Wrapper<Value> {
216+
let value: Value
217+
}
218+
219+
// CHECK-LABEL: @$s4main17wrapTupleElementsyAA7WrapperVyxGxQp_txxQpRvzlF
220+
// CHECK-SAME: $@convention(thin) <each T> (@pack_guaranteed Pack{repeat each T}) -> @pack_out Pack{repeat Wrapper<each T>}
221+
func wrapTupleElements<each T>(_ value: repeat each T) -> (repeat Wrapper<each T>) {
222+
// CHECK: [[VALUES:%.*]] = alloc_stack [lexical] $(repeat Wrapper<each T>), let,
223+
// CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0
224+
// CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1
225+
// CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T}
226+
// CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word)
227+
// CHECK: bb1([[IDX:%.*]] : $Builtin.Word)
228+
// CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1
229+
// CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb3, bb2
230+
// CHECK: bb2:
231+
// CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat Wrapper<each T>}
232+
// CHECK-NEXT: open_pack_element [[INDEX]] of <each T> at <Pack{repeat each T}>, shape $T, uuid [[UUID:".*"]]
233+
// CHECK-NEXT: [[ELT_ADDR:%.*]] = tuple_pack_element_addr [[INDEX]] of [[VALUES]] : $*(repeat Wrapper<each T>) as $*Wrapper<@pack_element([[UUID]]) T>
234+
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Wrapper<@pack_element([[UUID]]) T>.Type
235+
// CHECK-NEXT: [[ARG_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %1 : $*Pack{repeat each T} as $*@pack_element([[UUID]]) T
236+
// CHECK-NEXT: [[ARG_COPY:%.*]] = alloc_stack $@pack_element([[UUID]]) T
237+
// CHECK-NEXT: copy_addr [[ARG_ELT_ADDR]] to [init] [[ARG_COPY]] : $*@pack_element([[UUID]]) T
238+
// CHECK-NEXT: // function_ref
239+
// CHECK-NEXT: [[INIT:%.*]] = function_ref @$s4main7WrapperV5valueACyxGx_tcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin Wrapper<τ_0_0>.Type) -> @out Wrapper<τ_0_0>
240+
// CHECK-NEXT: apply [[INIT]]<@pack_element([[UUID]]) T>([[ELT_ADDR]], [[ARG_COPY]], [[METATYPE]])
241+
// CHECK-NEXT: dealloc_stack [[ARG_COPY]]
242+
// CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word
243+
// CHECK-NEXT: br bb1([[NEXT_IDX]] : $Builtin.Word)
244+
// CHECK: bb3:
245+
let values = (repeat Wrapper(value: each value))
246+
247+
// CHECK-NEXT: [[VALUES_COPY:%.*]] = alloc_stack $(repeat Wrapper<each T>)
248+
// CHECK-NEXT: copy_addr [[VALUES]] to [init] [[VALUES_COPY]] : $*(repeat Wrapper<each T>)
249+
// CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0
250+
// CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1
251+
// CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T}
252+
// CHECK-NEXT: br bb4([[ZERO]] : $Builtin.Word)
253+
// CHECK: bb4([[IDX:%.*]] : $Builtin.Word)
254+
// CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1
255+
// CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb6, bb5
256+
// CHECK: bb5:
257+
// CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat Wrapper<each T>}
258+
// CHECK-NEXT: open_pack_element [[INDEX]] of <each T> at <Pack{repeat each T}>, shape $T, uuid [[UUID:".*"]]
259+
// CHECK-NEXT: [[OUT_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %0 : $*Pack{repeat Wrapper<each T>} as $*Wrapper<@pack_element([[UUID]]) T>
260+
// CHECK-NEXT: [[VALUES_COPY_ELT_ADDR:%.*]] = tuple_pack_element_addr [[INDEX]] of [[VALUES_COPY]] : $*(repeat Wrapper<each T>) as $*Wrapper<@pack_element([[UUID]]) T>
261+
// CHECK-NEXT: copy_addr [take] [[VALUES_COPY_ELT_ADDR]] to [init] [[OUT_ELT_ADDR]] : $*Wrapper<@pack_element([[UUID]]) T>
262+
// CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word
263+
// CHECK-NEXT: br bb4([[NEXT_IDX]] : $Builtin.Word)
264+
// CHECK: bb6:
265+
// CHECK-NEXT: dealloc_stack [[VALUES_COPY]] :
266+
// CHECK-NEXT: destroy_addr [[VALUES]] :
267+
// CHECK-NEXT: dealloc_stack [[VALUES]] :
268+
// CHECK-NEXT: [[RET:%.*]] = tuple ()
269+
// CHECK-NEXT: return [[RET]] : $()
270+
return values
271+
}

0 commit comments

Comments
 (0)