Merge pull request #12675 from rjmccall/labeled-setter-parameters-4.1

[4.1] Handle labeled singleton tuples in the setter value argument
diff --git a/lib/SILGen/ArgumentSource.cpp b/lib/SILGen/ArgumentSource.cpp
index 1ed7c72..5661f17 100644
--- a/lib/SILGen/ArgumentSource.cpp
+++ b/lib/SILGen/ArgumentSource.cpp
@@ -59,8 +59,26 @@
     Storage.get<RValueStorage>(StoredKind).Value.rewriteType(newType);
     return;
   case Kind::Expr:
-    Expr *expr = Storage.get<Expr*>(StoredKind);
-    if (expr->getType()->isEqual(newType)) return;
+    Expr *&expr = Storage.get<Expr*>(StoredKind);
+    CanType oldType = expr->getType()->getCanonicalType();
+
+    // Usually nothing is required.
+    if (oldType == newType) return;
+
+    // Sometimes we need to wrap the expression in a single-element tuple.
+    // This is only necessary because we don't break down the argument list
+    // when dealing with SILGenApply.
+    if (auto newTuple = dyn_cast<TupleType>(newType)) {
+      if (newTuple->getNumElements() == 1 &&
+          newTuple.getElementType(0) == oldType) {
+        expr = TupleExpr::create(newType->getASTContext(),
+                                 SourceLoc(), expr, {}, {}, SourceLoc(),
+                                 /*trailing closure*/ false,
+                                 /*implicit*/ true, newType);
+        return;
+      }
+    }
+
     llvm_unreachable("unimplemented! hope it doesn't happen");
   }
   llvm_unreachable("bad kind");
diff --git a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
index c09b5da..fc360c6 100644
--- a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
+++ b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
@@ -89,3 +89,7 @@
 void noescapeBlockAlias(__attribute__((noescape)) dispatch_block_t block);
 void noescapeNonnullBlockAlias(__attribute__((noescape)) _Nonnull dispatch_block_t block);
 void escapeBlockAlias(dispatch_block_t block);
+
+@interface ObjectWithSplitProperty : NSObject
+@property (nonatomic, setter=private_setFlagForSomething:) BOOL flagForSomething;
+@end
diff --git a/test/SILGen/objc_properties.swift b/test/SILGen/objc_properties.swift
index 0362be4..350ef03 100644
--- a/test/SILGen/objc_properties.swift
+++ b/test/SILGen/objc_properties.swift
@@ -248,3 +248,11 @@
 // CHECK-LABEL: sil hidden @_T015objc_properties15HasLazyPropertyC6windowSo8NSObjectCSgvg : $@convention(method) (@guaranteed HasLazyProperty) -> @owned Optional<NSObject> {
 // CHECK: class_method %0 : $HasLazyProperty, #HasLazyProperty.instanceMethod!1 : (HasLazyProperty) -> () -> NSObject?
 // CHECK: return
+
+//   The way we import this setter splits the name into the parameter list,
+//   which can cause fits for SILGenApply the way it's currently implemented.
+// CHECK-LABEL: sil hidden @_T015objc_properties26testPropSetWithPreposition
+func testPropSetWithPreposition(object: ObjectWithSplitProperty?) {
+  // CHECK: #ObjectWithSplitProperty.flagForSomething!setter.1.foreign : (ObjectWithSplitProperty) -> (Bool) -> (), $@convention(objc_method) ({{Bool|ObjCBool}}, ObjectWithSplitProperty) -> ()
+  object?.flagForSomething = false
+}