Skip to content

Commit 5cf855d

Browse files
committed
Make bridged String and collection types conform to CVarArg.
This allows String, Array, Dictionary, and Set to be passed as variadic arguments to Cocoa APIs like NSLog, NSPredicate, stringWithFormat:, etc. rdar://problem/27651717
1 parent f395524 commit 5cf855d

File tree

7 files changed

+41
-11
lines changed

7 files changed

+41
-11
lines changed

lib/AST/ASTContext.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4073,9 +4073,14 @@ ASTContext::getBridgedToObjC(const DeclContext *dc, Type type,
40734073
*bridgedValueType = type;
40744074

40754075
// Find the Objective-C class type we bridge to.
4076-
return ProtocolConformance::getTypeWitnessByName(
4077-
type, conformance->getConcrete(), Id_ObjectiveCType,
4078-
resolver);
4076+
if (conformance->isConcrete()) {
4077+
return ProtocolConformance::getTypeWitnessByName(
4078+
type, conformance->getConcrete(), Id_ObjectiveCType,
4079+
resolver);
4080+
} else {
4081+
return type->castTo<ArchetypeType>()->getNestedType(Id_ObjectiveCType)
4082+
.getValue();
4083+
}
40794084
}
40804085

40814086
// Do we conform to Error?

stdlib/public/SDK/Foundation/Foundation.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,3 +1550,20 @@ extension AnyHashable : _ObjectiveCBridgeable {
15501550
}
15511551
}
15521552

1553+
//===----------------------------------------------------------------------===//
1554+
// CVarArg for bridged types
1555+
//===----------------------------------------------------------------------===//
1556+
1557+
extension CVarArg where Self: _ObjectiveCBridgeable {
1558+
/// Default implementation for bridgeable types.
1559+
public var _cVarArgEncoding: [Int] {
1560+
let object = self._bridgeToObjectiveC()
1561+
_autorelease(object)
1562+
return _encodeBitsAsWords(object)
1563+
}
1564+
}
1565+
1566+
extension String: CVarArg {}
1567+
extension Array: CVarArg {}
1568+
extension Dictionary: CVarArg {}
1569+
extension Set: CVarArg {}

stdlib/public/core/VarArgs.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public func getVaList(_ args: [CVarArg]) -> CVaListPointer {
107107
}
108108
#endif
109109

110-
public func _encodeBitsAsWords<T : CVarArg>(_ x: T) -> [Int] {
110+
public func _encodeBitsAsWords<T>(_ x: T) -> [Int] {
111111
let result = [Int](
112112
repeating: 0,
113113
count: (MemoryLayout<T>.size + MemoryLayout<Int>.size - 1) / MemoryLayout<Int>.size)

test/Interpreter/SDK/Foundation_NSExpression.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import Foundation
99

1010
// Test overlain variadic methods.
11-
let expression = NSExpression(format: "(3 + 2)**2", "LLLL" as NSString, "BBBB" as NSString)
11+
let expression = NSExpression(format: "(3 + 2)**2", "LLLL", "BBBB")
1212
let result = expression.expressionValue(with: expression, context:nil) as! NSNumber
1313
let number = result.stringValue
1414
print(number)

test/Interpreter/SDK/Foundation_NSLog.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ testNSLog()
1919
// CHECK: 1 is the loneliest number that you'll ever do
2020
NSLog(
2121
"%@ is the loneliest number that you'll ever %@",
22-
NSNumber(value: 1), "do" as NSString
22+
NSNumber(value: 1), "do"
2323
)

test/Interpreter/SDK/Foundation_NSPredicate.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import Foundation
88

99
// Test overlain variadic methods.
10-
let s = NSPredicate(format: "(lastName like[cd] %@) AND (birthday > %@)", "LLLL" as NSString, "BBBB" as NSString)
10+
let s = NSPredicate(format: "(lastName like[cd] %@) AND (birthday > %@)", "LLLL", "BBBB")
1111
print(s.predicateFormat)
1212

1313
// CHECK: lastName LIKE[cd] "LLLL" AND birthday > "BBBB"

test/Interpreter/SDK/Foundation_NSString.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,22 +135,30 @@ testComparisons()
135135
// Test overlain variadic methods.
136136
// CHECK-LABEL: Variadic methods:
137137
print("Variadic methods:")
138+
// Check that it works with bridged Strings.
138139
// CHECK-NEXT: x y
139-
print(NSString(format: "%@ %@", "x" as NSString, "y" as NSString))
140+
print(NSString(format: "%@ %@", "x", "y"))
141+
// Check that it works with bridged Arrays and Dictionaries.
142+
// CHECK-NEXT: (
143+
// CHECK-NEXT: x
144+
// CHECK-NEXT: ) {
145+
// CHECK-NEXT: y = z;
146+
// CHECK-NEXT: }
147+
print(NSString(format: "%@ %@", ["x"], ["y": "z"]))
140148
// CHECK-NEXT: 1{{.*}}024,25
141149
print(NSString(
142150
format: "%g",
143151
locale: Locale(identifier: "fr_FR"),
144152
1024.25
145153
))
146154
// CHECK-NEXT: x y z
147-
print(("x " as NSString).appendingFormat("%@ %@", "y" as NSString, "z" as NSString))
155+
print(("x " as NSString).appendingFormat("%@ %@", "y", "z"))
148156
// CHECK-NEXT: a b c
149157
let s = NSMutableString(string: "a ")
150-
s.appendFormat("%@ %@", "b" as NSString, "c" as NSString)
158+
s.appendFormat("%@ %@", "b", "c")
151159
print(s)
152160

153-
let m = NSMutableString.localizedStringWithFormat("<%@ %@>", "q" as NSString, "r" as NSString)
161+
let m = NSMutableString.localizedStringWithFormat("<%@ %@>", "q", "r")
154162
// CHECK-NEXT: <q r>
155163
print(m)
156164
m.append(" lever")

0 commit comments

Comments
 (0)