Merge pull request #21396 from slavapestov/enum-curry-thunk-regression-5.0

SILGen: Fix partial application of enum case with one-element labeled tuple [5.0]
diff --git a/lib/SILGen/RValue.cpp b/lib/SILGen/RValue.cpp
index b38b284..98ed559 100644
--- a/lib/SILGen/RValue.cpp
+++ b/lib/SILGen/RValue.cpp
@@ -318,13 +318,8 @@
                 KIND == ImplodeKind::Copy, "Not handled by init");
   bool isInit = (KIND == ImplodeKind::Forward);
 
-  // First, unwrap one-element tuples, since we cannot lower them.
-  auto tupleType = dyn_cast<TupleType>(type);
-  if (tupleType && tupleType->getNumElements() == 1)
-    type = tupleType.getElementType(0);
-
   // If the element has non-tuple type, just serve it up to the initialization.
-  tupleType = dyn_cast<TupleType>(type);
+  auto tupleType = dyn_cast<TupleType>(type);
   if (!tupleType) {
     // We take the first value.
     ManagedValue result = values[0];
diff --git a/test/SILGen/enum_curry_thunks.swift b/test/SILGen/enum_curry_thunks.swift
new file mode 100644
index 0000000..f897085
--- /dev/null
+++ b/test/SILGen/enum_curry_thunks.swift
@@ -0,0 +1,51 @@
+// RUN: %target-swift-emit-silgen -parse-as-library %s | %FileCheck %s
+
+enum PartialApplyEnumPayload<T, U> {
+  case Left(T)
+  case Both(T, U)
+
+  case LeftWithLabel(left: T)
+  case BothWithLabel(left: T, right: U)
+
+  case TupleWithLabel(both: (T, U))
+
+  // Note: SILGen can emit these thunks correctly, but we disabled
+  // the feature since calling the constructor directly (without a
+  // thunk) doesn't work yet.
+  /* case Variadic(_: Int...)
+  case VariadicWithLabel(indices: Int...)
+  case VariadicTuple(_: (Int, Int)...)
+  case VariadicWithOther(String, _: Int...) */
+
+  case Autoclosure(@autoclosure () -> ())
+}
+
+struct S {}
+struct C {}
+
+func partialApplyEnumCases(_ x: S, y: C) {
+  _ = PartialApplyEnumPayload<S, C>.Left
+  _ = PartialApplyEnumPayload<S, C>.Both
+  _ = PartialApplyEnumPayload<S, C>.LeftWithLabel
+  _ = PartialApplyEnumPayload<S, C>.TupleWithLabel
+  /* _ = PartialApplyEnumPayload<S, C>.Variadic
+  _ = PartialApplyEnumPayload<S, C>.VariadicWithLabel
+  _ = PartialApplyEnumPayload<S, C>.VariadicTuple
+  _ = PartialApplyEnumPayload<S, C>.VariadicWithOther */
+  _ = PartialApplyEnumPayload<S, C>.Autoclosure
+}
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$s17enum_curry_thunks23PartialApplyEnumPayloadO4LeftyACyxq_GxcAEmr0_lFTc : $@convention(thin) <T, U> (@thin PartialApplyEnumPayload<T, U>.Type) -> @owned @callee_guaranteed (@in_guaranteed T) -> @out PartialApplyEnumPayload<T, U> {
+// CHECK-LABEL: sil shared [transparent] @$s17enum_curry_thunks23PartialApplyEnumPayloadO4LeftyACyxq_GxcAEmr0_lF : $@convention(method) <T, U> (@in T, @thin PartialApplyEnumPayload<T, U>.Type) -> @out PartialApplyEnumPayload<T, U> {
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$s17enum_curry_thunks23PartialApplyEnumPayloadO4BothyACyxq_Gx_q_tcAEmr0_lFTc : $@convention(thin) <T, U> (@thin PartialApplyEnumPayload<T, U>.Type) -> @owned @callee_guaranteed (@in_guaranteed T, @in_guaranteed U) -> @out PartialApplyEnumPayload<T, U> {
+// CHECK-LABEL: sil shared [transparent] @$s17enum_curry_thunks23PartialApplyEnumPayloadO4BothyACyxq_Gx_q_tcAEmr0_lF : $@convention(method) <T, U> (@in T, @in U, @thin PartialApplyEnumPayload<T, U>.Type) -> @out PartialApplyEnumPayload<T, U> {
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$s17enum_curry_thunks23PartialApplyEnumPayloadO13LeftWithLabelyACyxq_Gx_tcAEmr0_lFTc : $@convention(thin) <T, U> (@thin PartialApplyEnumPayload<T, U>.Type) -> @owned @callee_guaranteed (@in_guaranteed T) -> @out PartialApplyEnumPayload<T, U> {
+// CHECK-LABEL: sil shared [transparent] @$s17enum_curry_thunks23PartialApplyEnumPayloadO13LeftWithLabelyACyxq_Gx_tcAEmr0_lF : $@convention(method) <T, U> (@in T, @thin PartialApplyEnumPayload<T, U>.Type) -> @out PartialApplyEnumPayload<T, U> {
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$s17enum_curry_thunks23PartialApplyEnumPayloadO14TupleWithLabelyACyxq_Gx_q_t_tcAEmr0_lFTc : $@convention(thin) <T, U> (@thin PartialApplyEnumPayload<T, U>.Type) -> @owned @callee_guaranteed (@in_guaranteed T, @in_guaranteed U) -> @out PartialApplyEnumPayload<T, U> {
+// CHECK-LABEL: sil shared [transparent] @$s17enum_curry_thunks23PartialApplyEnumPayloadO14TupleWithLabelyACyxq_Gx_q_t_tcAEmr0_lF : $@convention(method) <T, U> (@in T, @in U, @thin PartialApplyEnumPayload<T, U>.Type) -> @out PartialApplyEnumPayload<T, U> {
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$s17enum_curry_thunks23PartialApplyEnumPayloadO11AutoclosureyACyxq_GyyXAcAEmr0_lFTc : $@convention(thin) <T, U> (@thin PartialApplyEnumPayload<T, U>.Type) -> @owned @callee_guaranteed (@guaranteed @callee_guaranteed () -> ()) -> @out PartialApplyEnumPayload<T, U> {
+// CHECK-LABEL: sil shared [transparent] @$s17enum_curry_thunks23PartialApplyEnumPayloadO11AutoclosureyACyxq_GyyXAcAEmr0_lF : $@convention(method) <T, U> (@owned @callee_guaranteed () -> (), @thin PartialApplyEnumPayload<T, U>.Type) -> @out PartialApplyEnumPayload<T, U> {
diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift
index ead4e21..8a8feb6 100644
--- a/test/SILGen/functions.swift
+++ b/test/SILGen/functions.swift
@@ -522,35 +522,3 @@
 
 // CHECK: // closure #1 () -> () in closure #1 () -> () in functions.testNoescape2() -> ()
 // CHECK-NEXT: sil private @$s9functions13testNoescape2yyFyyXEfU_yycfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
-
-enum PartialApplyEnumPayload<T, U> {
-  case Left(T)
-  case Right(U)
-}
-
-struct S {}
-struct C {}
-
-func partialApplyEnumCases(_ x: S, y: C) {
-  let left = PartialApplyEnumPayload<S, C>.Left
-  let left2 = left(S())
-
-  let right = PartialApplyEnumPayload<S, C>.Right
-  let right2 = right(C())
-}
-
-// CHECK-LABEL: sil shared [transparent] [thunk] @$s9functions23PartialApplyEnumPayloadO4Left{{[_0-9a-zA-Z]*}}F
-// CHECK:         [[UNCURRIED:%.*]] = function_ref @$s9functions23PartialApplyEnumPayloadO4Left{{[_0-9a-zA-Z]*}}F
-// CHECK:         [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[UNCURRIED]]<T, U>(%0)
-// CHECK:         [[CANONICAL_THUNK:%.*]] = function_ref @$sx9functions23PartialApplyEnumPayloadOyxq_GIegir_xADIegnr_r0_lTR : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in τ_0_0) -> @out PartialApplyEnumPayload<τ_0_0, τ_0_1>) -> @out PartialApplyEnumPayload<τ_0_0, τ_0_1>
-// CHECK:         [[THUNKED_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK]]<T, U>([[CLOSURE]])
-// CHECK:         return [[THUNKED_CLOSURE]]
-// CHECK: } // end sil function '$s9functions23PartialApplyEnumPayloadO4Left{{[_0-9a-zA-Z]*}}F'
-
-// CHECK-LABEL: sil shared [transparent] [thunk] @$s9functions23PartialApplyEnumPayloadO5Right{{[_0-9a-zA-Z]*}}F
-// CHECK:         [[UNCURRIED:%.*]] = function_ref @$s9functions23PartialApplyEnumPayloadO5Right{{[_0-9a-zA-Z]*}}F
-// CHECK:         [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[UNCURRIED]]<T, U>(%0)
-// CHECK:         [[CANONICAL_THUNK:%.*]] = function_ref @$sq_9functions23PartialApplyEnumPayloadOyxq_GIegir_q_ADIegnr_r0_lTR : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_1, @guaranteed @callee_guaranteed (@in τ_0_1) -> @out PartialApplyEnumPayload<τ_0_0, τ_0_1>) -> @out PartialApplyEnumPayload<τ_0_0, τ_0_1>
-// CHECK:         [[THUNKED_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK]]<T, U>([[CLOSURE]])
-// CHECK:         return [[THUNKED_CLOSURE]]
-// CHECK: } // end sil function '$s9functions23PartialApplyEnumPayloadO5Right{{[_0-9a-zA-Z]*}}F'