Skip to content

Commit 9b2a1cf

Browse files
authored
Merge pull request swiftlang#21924 from slavapestov/enum-element-trailing-closure
Fix enum element constructor call with trailing closure
2 parents 664e565 + 1eb3548 commit 9b2a1cf

File tree

2 files changed

+72
-37
lines changed

2 files changed

+72
-37
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,9 +2292,13 @@ static void emitTupleShuffleExprInto(RValueEmitter &emitter,
22922292
// Map outer initializations into a tuple of inner initializations:
22932293
// - fill out the initialization elements with null
22942294
TupleInitialization innerTupleInit;
2295-
CanTupleType innerTuple =
2296-
cast<TupleType>(E->getSubExpr()->getType()->getCanonicalType());
2297-
innerTupleInit.SubInitializations.resize(innerTuple->getNumElements());
2295+
if (E->isSourceScalar()) {
2296+
innerTupleInit.SubInitializations.push_back(nullptr);
2297+
} else {
2298+
CanTupleType innerTuple =
2299+
cast<TupleType>(E->getSubExpr()->getType()->getCanonicalType());
2300+
innerTupleInit.SubInitializations.resize(innerTuple->getNumElements());
2301+
}
22982302

22992303
// Map all the outer initializations to their appropriate targets.
23002304
for (unsigned outerIndex = 0; outerIndex != outerInits.size(); outerIndex++) {
@@ -2312,14 +2316,20 @@ static void emitTupleShuffleExprInto(RValueEmitter &emitter,
23122316
#endif
23132317

23142318
// Emit the sub-expression into the tuple initialization we just built.
2315-
emitter.SGF.emitExprInto(E->getSubExpr(), &innerTupleInit);
2319+
if (E->isSourceScalar()) {
2320+
emitter.SGF.emitExprInto(E->getSubExpr(),
2321+
innerTupleInit.SubInitializations[0].get());
2322+
} else {
2323+
emitter.SGF.emitExprInto(E->getSubExpr(), &innerTupleInit);
2324+
}
23162325

23172326
outerTupleInit->finishInitialization(emitter.SGF);
23182327
}
23192328

23202329
RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E,
23212330
SGFContext C) {
2322-
assert(!E->isSourceScalar());
2331+
// FIXME: Once we're no longer using this code path for enum element payloads,
2332+
// also assert that !E->isSourceScalar().
23232333
assert(!E->isResultScalar());
23242334

23252335
// If we're emitting into an initialization, we can try shuffling the
@@ -2333,7 +2343,11 @@ RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E,
23332343

23342344
// Emit the sub-expression tuple and destructure it into elements.
23352345
SmallVector<RValue, 4> elements;
2336-
visit(E->getSubExpr()).extractElements(elements);
2346+
if (E->isSourceScalar()) {
2347+
elements.push_back(visit(E->getSubExpr()));
2348+
} else {
2349+
visit(E->getSubExpr()).extractElements(elements);
2350+
}
23372351

23382352
// Prepare a new tuple to hold the shuffled result.
23392353
RValue result(E->getType()->getCanonicalType());

test/SILGen/enum.swift

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11

2-
// RUN: %target-swift-emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck %s
3-
4-
precedencegroup AssignmentPrecedence { assignment: true }
5-
6-
enum Optional<Wrapped> {
7-
case none
8-
case some(Wrapped)
9-
}
2+
// RUN: %target-swift-emit-silgen -parse-as-library %s | %FileCheck %s
103

114
enum Boolish {
125
case falsy
136
case truthy
147
}
158

16-
// CHECK-LABEL: sil hidden [ossa] @$ss13Boolish_casesyyF
9+
// CHECK-LABEL: sil hidden [ossa] @$s4enum13Boolish_casesyyF
1710
func Boolish_cases() {
1811
// CHECK: [[BOOLISH:%[0-9]+]] = metatype $@thin Boolish.Type
1912
// CHECK-NEXT: [[FALSY:%[0-9]+]] = enum $Boolish, #Boolish.falsy!enumelt
@@ -24,18 +17,16 @@ func Boolish_cases() {
2417
_ = Boolish.truthy
2518
}
2619

27-
struct Int {}
28-
2920
enum Optionable {
3021
case nought
3122
case mere(Int)
3223
}
3324

34-
// CHECK-LABEL: sil hidden [ossa] @$ss16Optionable_casesyySiF
25+
// CHECK-LABEL: sil hidden [ossa] @$s4enum16Optionable_casesyySiF
3526
func Optionable_cases(_ x: Int) {
3627

3728
// CHECK: [[METATYPE:%.*]] = metatype $@thin Optionable.Type
38-
// CHECK: [[FN:%.*]] = function_ref @$ss10OptionableO4mereyABSicABmF
29+
// CHECK: [[FN:%.*]] = function_ref @$s4enum10OptionableO4mereyACSicACmFTc
3930
// CHECK-NEXT: [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
4031
// CHECK-NEXT: destroy_value [[CTOR]]
4132
_ = Optionable.mere
@@ -45,13 +36,13 @@ func Optionable_cases(_ x: Int) {
4536
_ = Optionable.mere(x)
4637
}
4738

48-
// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$ss10OptionableO4mereyABSicABmF
49-
// CHECK: [[FN:%.*]] = function_ref @$ss10OptionableO4mereyABSicABmF
39+
// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$s4enum10OptionableO4mereyACSicACmF
40+
// CHECK: [[FN:%.*]] = function_ref @$s4enum10OptionableO4mereyACSicACmF
5041
// CHECK-NEXT: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
5142
// CHECK-NEXT: return [[METHOD]]
5243
// CHECK-NEXT: }
5344

54-
// CHECK-LABEL: sil shared [transparent] [ossa] @$ss10OptionableO4mereyABSicABmF
45+
// CHECK-LABEL: sil shared [transparent] [ossa] @$s4enum10OptionableO4mereyACSicACmF
5546
// CHECK: [[RES:%.*]] = enum $Optionable, #Optionable.mere!enumelt.1, %0 : $Int
5647
// CHECK-NEXT: return [[RES]] : $Optionable
5748
// CHECK-NEXT: }
@@ -65,11 +56,11 @@ enum AddressOnly {
6556
case phantom(S)
6657
}
6758

68-
// CHECK-LABEL: sil hidden [ossa] @$ss17AddressOnly_casesyys1SVF
59+
// CHECK-LABEL: sil hidden [ossa] @$s4enum17AddressOnly_casesyyAA1SVF
6960
func AddressOnly_cases(_ s: S) {
7061

7162
// CHECK: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
72-
// CHECK: [[FN:%.*]] = function_ref @$ss11AddressOnlyO4mereyABs1P_pcABmF
63+
// CHECK: [[FN:%.*]] = function_ref @$s4enum11AddressOnlyO4mereyAcA1P_pcACmFTc
7364
// CHECK-NEXT: [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
7465
// CHECK-NEXT: destroy_value [[CTOR]]
7566
_ = AddressOnly.mere
@@ -105,29 +96,29 @@ func AddressOnly_cases(_ s: S) {
10596
// CHECK: return
10697
}
10798

108-
// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$ss11AddressOnlyO4mereyABs1P_pcABmF
109-
// CHECK: [[FN:%.*]] = function_ref @$ss11AddressOnlyO4mereyABs1P_pcABmF
99+
// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$s4enum11AddressOnlyO4mereyAcA1P_pcACmFTc
100+
// CHECK: [[FN:%.*]] = function_ref @$s4enum11AddressOnlyO4mereyAcA1P_pcACmF
110101
// CHECK-NEXT: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
111102
// CHECK-NEXT: // function_ref
112-
// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$ss1P_ps11AddressOnlyOIegir_sAA_pACIegnr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed @callee_guaranteed (@in P) -> @out AddressOnly) -> @out AddressOnly
103+
// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$s4enum1P_pAA11AddressOnlyOIegir_AaB_pADIegnr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed @callee_guaranteed (@in P) -> @out AddressOnly) -> @out AddressOnly
113104
// CHECK-NEXT: [[CANONICAL_THUNK:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK_FN]]([[METHOD]])
114105
// CHECK-NEXT: return [[CANONICAL_THUNK]] : $@callee_guaranteed (@in_guaranteed P) -> @out AddressOnly
115106
// CHECK-NEXT: }
116107

117-
// CHECK-LABEL: sil shared [transparent] [ossa] @$ss11AddressOnlyO4mereyABs1P_pcABmF : $@convention
108+
// CHECK-LABEL: sil shared [transparent] [ossa] @$s4enum11AddressOnlyO4mereyAcA1P_pcACmF : $@convention
118109
// CHECK: bb0([[ARG0:%.*]] : $*AddressOnly, [[ARG1:%.*]] : $*P, [[ARG2:%.*]] : $@thin AddressOnly.Type):
119110
// CHECK: [[RET_DATA:%.*]] = init_enum_data_addr [[ARG0]] : $*AddressOnly, #AddressOnly.mere!enumelt.1
120111
// CHECK-NEXT: copy_addr [take] [[ARG1]] to [initialization] [[RET_DATA]] : $*P
121112
// CHECK-NEXT: inject_enum_addr [[ARG0]] : $*AddressOnly, #AddressOnly.mere!enumelt.1
122113
// CHECK: return
123-
// CHECK-NEXT: } // end sil function '$ss11AddressOnlyO4mereyABs1P_pcABmF'
114+
// CHECK-NEXT: } // end sil function '$s4enum11AddressOnlyO4mereyAcA1P_pcACmF'
124115

125116
enum PolyOptionable<T> {
126117
case nought
127118
case mere(T)
128119
}
129120

130-
// CHECK-LABEL: sil hidden [ossa] @$ss20PolyOptionable_casesyyxlF
121+
// CHECK-LABEL: sil hidden [ossa] @$s4enum20PolyOptionable_casesyyxlF
131122
func PolyOptionable_cases<T>(_ t: T) {
132123

133124
// CHECK: [[METATYPE:%.*]] = metatype $@thin PolyOptionable<T>.Type
@@ -154,7 +145,7 @@ func PolyOptionable_cases<T>(_ t: T) {
154145

155146
// The substituted type is loadable and trivial here
156147

157-
// CHECK-LABEL: sil hidden [ossa] @$ss32PolyOptionable_specialized_casesyySiF
148+
// CHECK-LABEL: sil hidden [ossa] @$s4enum32PolyOptionable_specialized_casesyySiF
158149
func PolyOptionable_specialized_cases(_ t: Int) {
159150

160151
// CHECK: [[METATYPE:%.*]] = metatype $@thin PolyOptionable<Int>.Type
@@ -172,23 +163,23 @@ func PolyOptionable_specialized_cases(_ t: Int) {
172163

173164
// Regression test for a bug where temporary allocations created as a result of
174165
// tuple implosion were not deallocated in enum constructors.
175-
struct String { var ptr: Builtin.NativeObject }
166+
struct String { var ptr: AnyObject }
176167

177168
enum Foo { case a(P, String) }
178169

179170
// Curry Thunk for Foo.a(_:)
180171
//
181-
// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$ss3FooO1ayABs1P_p_SStcABmF
182-
// CHECK: [[FN:%.*]] = function_ref @$ss3FooO1ayABs1P_p_SStcABmF
172+
// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$s4enum3FooO1ayAcA1P_p_AA6StringVtcACmFTc
173+
// CHECK: [[FN:%.*]] = function_ref @$s4enum3FooO1ayAcA1P_p_AA6StringVtcACmF
183174
// CHECK-NEXT: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
184175
// CHECK-NEXT: // function_ref
185-
// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$ss1P_pSSs3FooOIegixr_sAA_pSSACIegngr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed String, @guaranteed @callee_guaranteed (@in P, @owned String) -> @out Foo) -> @out Foo
176+
// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$s4enum1P_pAA6StringVAA3FooOIegixr_AaB_pAdFIegngr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed String, @guaranteed @callee_guaranteed (@in P, @owned String) -> @out Foo) -> @out Foo
186177
// CHECK-NEXT: [[CANONICAL_THUNK:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK_FN]]([[METHOD]])
187178
// CHECK-NEXT: return [[CANONICAL_THUNK]]
188179
// CHECK-NEXT: }
189180

190181
// Foo.a(_:)
191-
// CHECK-LABEL: sil shared [transparent] [ossa] @$ss3FooO1ayABs1P_p_SStcABmF
182+
// CHECK-LABEL: sil shared [transparent] [ossa] @$s4enum3FooO1ayAcA1P_p_AA6StringVtcACmF
192183
// CHECK: bb0([[ARG0:%.*]] : $*Foo, [[ARG1:%.*]] : $*P, [[ARG2:%.*]] : @owned $String, [[ARG3:%.*]] : $@thin Foo.Type):
193184
// CHECK: [[PAYLOAD:%.*]] = init_enum_data_addr [[ARG0]] : $*Foo, #Foo.a!enumelt.1
194185
// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PAYLOAD]] : $*(P, String), 0
@@ -197,7 +188,7 @@ enum Foo { case a(P, String) }
197188
// CHECK-NEXT: store [[ARG2]] to [init] [[RIGHT]]
198189
// CHECK-NEXT: inject_enum_addr [[ARG0]] : $*Foo, #Foo.a!enumelt.1
199190
// CHECK: return
200-
// CHECK-NEXT: } // end sil function '$ss3FooO1ayABs1P_p_SStcABmF'
191+
// CHECK-NEXT: } // end sil function '$s4enum3FooO1ayAcA1P_p_AA6StringVtcACmF'
201192

202193
func Foo_cases() {
203194
_ = Foo.a
@@ -213,3 +204,33 @@ enum Indirect<T> {
213204
func makeIndirectEnum<T>(_ payload: T) -> Indirect<T> {
214205
return Indirect.payload((payload, other: payload))
215206
}
207+
208+
// https://bugs.swift.org/browse/SR-9675
209+
210+
enum TrailingClosureConcrete {
211+
case label(fn: () -> Int)
212+
case noLabel(() -> Int)
213+
case twoElementsLabel(x: Int, fn: () -> Int)
214+
case twoElementsNoLabel(_ x: Int, _ fn: () -> Int)
215+
}
216+
217+
func useTrailingClosureConcrete() {
218+
_ = TrailingClosureConcrete.label { 0 }
219+
_ = TrailingClosureConcrete.noLabel { 0 }
220+
_ = TrailingClosureConcrete.twoElementsLabel(x: 0) { 0 }
221+
_ = TrailingClosureConcrete.twoElementsNoLabel(0) { 0 }
222+
}
223+
224+
enum TrailingClosureGeneric<T> {
225+
case label(fn: () -> T)
226+
case noLabel(() -> T)
227+
case twoElementsLabel(x: T, fn: () -> T)
228+
case twoElementsNoLabel(_ x: T, _ fn: () -> T)
229+
}
230+
231+
func useTrailingClosureGeneric<T>(t: T) {
232+
_ = TrailingClosureGeneric<T>.label { t }
233+
_ = TrailingClosureGeneric<T>.noLabel { t }
234+
_ = TrailingClosureGeneric<T>.twoElementsLabel(x: t) { t }
235+
_ = TrailingClosureGeneric<T>.twoElementsNoLabel(t) { t }
236+
}

0 commit comments

Comments
 (0)