@@ -1255,23 +1255,30 @@ internal func _stdlib_NSSet_allObjects(_ nss: _NSSet) ->
1255
1255
1256
1256
//===--- Compiler conversion/casting entry points for Set<Element> --------===//
1257
1257
1258
- #if _runtime(_ObjC)
1258
+ func _impossible<T>(_:T.Type) -> T {
1259
+ Builtin.unreachable()
1260
+ }
1261
+
1262
+ func _unsafeUpcast<T, U>(_ x: T, to: U.Type) -> U {
1263
+ _sanityCheck(x is U)
1264
+ return x as? U ?? _impossible(U.self)
1265
+ }
1266
+
1259
1267
/// Perform a non-bridged upcast that always succeeds.
1260
1268
///
1261
1269
/// - Precondition: `BaseValue` is a base class or base `@objc`
1262
1270
/// protocol (such as `AnyObject`) of `DerivedValue`.
1263
1271
public func _setUpCast<DerivedValue, BaseValue>(_ source: Set<DerivedValue>)
1264
1272
-> Set<BaseValue> {
1265
- _sanityCheck(_isClassOrObjCExistential(BaseValue.self))
1266
- _sanityCheck(_isClassOrObjCExistential(DerivedValue.self))
1267
-
1268
1273
var builder = _SetBuilder<BaseValue>(count: source.count)
1269
- for member in source {
1270
- builder.add(member: unsafeBitCast(member , to: BaseValue.self))
1274
+ for x in source {
1275
+ builder.add(member: _unsafeUpcast(x , to: BaseValue.self))
1271
1276
}
1272
1277
return builder.take()
1273
1278
}
1274
1279
1280
+ #if _runtime(_ObjC)
1281
+
1275
1282
/// Implements an unconditional upcast that involves bridging.
1276
1283
///
1277
1284
/// The cast can fail if bridging fails.
@@ -1288,6 +1295,7 @@ public func _setBridgeToObjectiveC<SwiftValue, ObjCValue>(
1288
1295
let valueBridgesDirectly =
1289
1296
_isBridgedVerbatimToObjectiveC(SwiftValue.self) ==
1290
1297
_isBridgedVerbatimToObjectiveC(ObjCValue.self)
1298
+
1291
1299
for member in source {
1292
1300
var bridgedMember: ObjCValue
1293
1301
if valueBridgesDirectly {
@@ -1303,6 +1311,8 @@ public func _setBridgeToObjectiveC<SwiftValue, ObjCValue>(
1303
1311
return result
1304
1312
}
1305
1313
1314
+ #endif
1315
+
1306
1316
/// Implements a forced downcast. This operation should have O(1) complexity.
1307
1317
///
1308
1318
/// The cast can fail if bridging fails. The actual checks and bridging can be
@@ -1313,20 +1323,23 @@ public func _setBridgeToObjectiveC<SwiftValue, ObjCValue>(
1313
1323
public func _setDownCast<BaseValue, DerivedValue>(_ source: Set<BaseValue>)
1314
1324
-> Set<DerivedValue> {
1315
1325
1316
- _sanityCheck(_isClassOrObjCExistential(BaseValue.self))
1317
- _sanityCheck(_isClassOrObjCExistential(DerivedValue.self))
1318
-
1319
- switch source._variantStorage {
1320
- case _VariantSetStorage.native(let nativeOwner):
1321
- return Set(
1322
- _immutableCocoaSet:
1323
- unsafeBitCast(nativeOwner, to: _NSSet.self))
1324
-
1325
- case _VariantSetStorage.cocoa(let cocoaStorage):
1326
- return Set(
1327
- _immutableCocoaSet:
1328
- unsafeBitCast(cocoaStorage, to: _NSSet.self))
1326
+ #if _runtime(_ObjC)
1327
+ if _isClassOrObjCExistential(BaseValue.self)
1328
+ && _isClassOrObjCExistential(DerivedValue.self) {
1329
+ switch source._variantStorage {
1330
+ case _VariantSetStorage.native(let nativeOwner):
1331
+ return Set(
1332
+ _immutableCocoaSet:
1333
+ unsafeBitCast(nativeOwner, to: _NSSet.self))
1334
+
1335
+ case _VariantSetStorage.cocoa(let cocoaStorage):
1336
+ return Set(
1337
+ _immutableCocoaSet:
1338
+ unsafeBitCast(cocoaStorage, to: _NSSet.self))
1339
+ }
1329
1340
}
1341
+ #endif
1342
+ return _setDownCastConditional(source)!
1330
1343
}
1331
1344
1332
1345
/// Implements a conditional downcast.
@@ -1339,20 +1352,14 @@ public func _setDownCast<BaseValue, DerivedValue>(_ source: Set<BaseValue>)
1339
1352
public func _setDownCastConditional<BaseValue, DerivedValue>(
1340
1353
_ source: Set<BaseValue>
1341
1354
) -> Set<DerivedValue>? {
1342
- _sanityCheck(_isClassOrObjCExistential(BaseValue.self))
1343
- _sanityCheck(_isClassOrObjCExistential(DerivedValue.self))
1344
-
1345
- var result = Set<DerivedValue>(minimumCapacity: source.count)
1346
- for member in source {
1347
- if let derivedMember = member as? DerivedValue {
1348
- result.insert(derivedMember)
1349
- continue
1350
- }
1351
- return nil
1352
- }
1353
- return result
1355
+ return try? Set(
1356
+ source.lazy.map {
1357
+ try ($0 as? DerivedValue).unwrappedOrError()
1358
+ })
1354
1359
}
1355
1360
1361
+ #if _runtime(_ObjC)
1362
+
1356
1363
/// Implements an unconditional downcast that involves bridging.
1357
1364
///
1358
1365
/// - Precondition: At least one of `SwiftValue` is a bridged value
@@ -1406,23 +1413,6 @@ public func _setBridgeFromObjectiveCConditional<
1406
1413
}
1407
1414
return result
1408
1415
}
1409
- #else
1410
-
1411
- public func _setUpCast<DerivedValue, BaseValue>(_ source: Set<DerivedValue>)
1412
- -> Set<BaseValue> {
1413
- fatalError("_setUpCast is unimplemented")
1414
- }
1415
-
1416
- public func _setDownCast<BaseValue, DerivedValue>(_ source: Set<BaseValue>)
1417
- -> Set<DerivedValue> {
1418
- fatalError("_setDownCast is unimplemented")
1419
- }
1420
-
1421
- public func _setDownCastConditional<BaseValue, DerivedValue>(
1422
- _ source: Set<BaseValue>
1423
- ) -> Set<DerivedValue>? {
1424
- fatalError("_setDownCastConditional is unimplemented")
1425
- }
1426
1416
1427
1417
#endif
1428
1418
@@ -2179,7 +2169,6 @@ internal func _stdlib_NSDictionary_allKeys(_ nsd: _NSDictionary)
2179
2169
2180
2170
//===--- Compiler conversion/casting entry points for Dictionary<K, V> ----===//
2181
2171
2182
- #if _runtime(_ObjC)
2183
2172
/// Perform a non-bridged upcast that always succeeds.
2184
2173
///
2185
2174
/// - Precondition: `BaseKey` and `BaseValue` are base classes or base `@objc`
@@ -2188,22 +2177,17 @@ internal func _stdlib_NSDictionary_allKeys(_ nsd: _NSDictionary)
2188
2177
public func _dictionaryUpCast<DerivedKey, DerivedValue, BaseKey, BaseValue>(
2189
2178
_ source: Dictionary<DerivedKey, DerivedValue>
2190
2179
) -> Dictionary<BaseKey, BaseValue> {
2191
- // FIXME: This crappy implementation is O(n) because it copies the
2192
- // data; a proper implementation would be O(1).
2193
-
2194
- _sanityCheck(_isClassOrObjCExistential(BaseKey.self))
2195
- _sanityCheck(_isClassOrObjCExistential(BaseValue.self))
2196
- _sanityCheck(_isClassOrObjCExistential(DerivedKey.self))
2197
- _sanityCheck(_isClassOrObjCExistential(DerivedValue.self))
2198
-
2199
2180
var result = Dictionary<BaseKey, BaseValue>(minimumCapacity: source.count)
2181
+
2200
2182
for (k, v) in source {
2201
- result[unsafeBitCast (k, to: BaseKey.self)] =
2202
- unsafeBitCast (v, to: BaseValue.self)
2183
+ result[_unsafeUpcast (k, to: BaseKey.self)]
2184
+ = _unsafeUpcast (v, to: BaseValue.self)
2203
2185
}
2204
2186
return result
2205
2187
}
2206
2188
2189
+ #if _runtime(_ObjC)
2190
+
2207
2191
/// Implements an unconditional upcast that involves bridging.
2208
2192
///
2209
2193
/// The cast can fail if bridging fails.
@@ -2263,6 +2247,7 @@ public func _dictionaryBridgeToObjectiveC<
2263
2247
2264
2248
return result
2265
2249
}
2250
+ #endif
2266
2251
2267
2252
/// Implements a forced downcast. This operation should have O(1) complexity.
2268
2253
///
@@ -2274,33 +2259,38 @@ public func _dictionaryBridgeToObjectiveC<
2274
2259
public func _dictionaryDownCast<BaseKey, BaseValue, DerivedKey, DerivedValue>(
2275
2260
_ source: Dictionary<BaseKey, BaseValue>
2276
2261
) -> Dictionary<DerivedKey, DerivedValue> {
2277
- _sanityCheck(_isClassOrObjCExistential(BaseKey.self))
2278
- _sanityCheck(_isClassOrObjCExistential(BaseValue.self))
2279
- _sanityCheck(_isClassOrObjCExistential(DerivedKey.self))
2280
- _sanityCheck(_isClassOrObjCExistential(DerivedValue.self))
2281
-
2282
- switch source._variantStorage {
2283
- case .native(let nativeOwner):
2284
- // FIXME(performance): this introduces an indirection through Objective-C
2285
- // runtime, even though we access native storage. But we cannot
2286
- // unsafeBitCast the owner object, because that would change the generic
2287
- // arguments.
2288
- //
2289
- // One way to solve this is to add a third, read-only, representation to
2290
- // variant storage: like _NativeDictionaryStorageOwner, but it would
2291
- // perform casts when accessing elements.
2292
- //
2293
- // Note: it is safe to treat the storage as immutable here because
2294
- // Dictionary will not mutate storage with reference count greater than 1.
2295
- return Dictionary(
2296
- _immutableCocoaDictionary:
2262
+
2263
+ #if _runtime(_ObjC)
2264
+ if _isClassOrObjCExistential(BaseKey.self)
2265
+ && _isClassOrObjCExistential(BaseValue.self)
2266
+ && _isClassOrObjCExistential(DerivedKey.self)
2267
+ && _isClassOrObjCExistential(DerivedValue.self) {
2268
+
2269
+ switch source._variantStorage {
2270
+ case .native(let nativeOwner):
2271
+ // FIXME(performance): this introduces an indirection through Objective-C
2272
+ // runtime, even though we access native storage. But we cannot
2273
+ // unsafeBitCast the owner object, because that would change the generic
2274
+ // arguments.
2275
+ //
2276
+ // One way to solve this is to add a third, read-only, representation to
2277
+ // variant storage: like _NativeDictionaryStorageOwner, but it would
2278
+ // perform casts when accessing elements.
2279
+ //
2280
+ // Note: it is safe to treat the storage as immutable here because
2281
+ // Dictionary will not mutate storage with reference count greater than 1.
2282
+ return Dictionary(
2283
+ _immutableCocoaDictionary:
2297
2284
unsafeBitCast(nativeOwner, to: _NSDictionary.self))
2298
2285
2299
- case .cocoa(let cocoaStorage):
2300
- return Dictionary(
2301
- _immutableCocoaDictionary:
2286
+ case .cocoa(let cocoaStorage):
2287
+ return Dictionary(
2288
+ _immutableCocoaDictionary:
2302
2289
unsafeBitCast(cocoaStorage, to: _NSDictionary.self))
2290
+ }
2303
2291
}
2292
+ #endif
2293
+ return _dictionaryDownCastConditional(source)!
2304
2294
}
2305
2295
2306
2296
/// Implements a conditional downcast.
@@ -2315,27 +2305,17 @@ public func _dictionaryDownCastConditional<
2315
2305
>(
2316
2306
_ source: Dictionary<BaseKey, BaseValue>
2317
2307
) -> Dictionary<DerivedKey, DerivedValue>? {
2318
- _sanityCheck(_isClassOrObjCExistential(BaseKey.self))
2319
- _sanityCheck(_isClassOrObjCExistential(BaseValue.self))
2320
- _sanityCheck(_isClassOrObjCExistential(DerivedKey.self))
2321
- _sanityCheck(_isClassOrObjCExistential(DerivedValue.self))
2322
-
2308
+
2323
2309
var result = Dictionary<DerivedKey, DerivedValue>()
2324
- for (key, value) in source {
2325
- if let derivedKey = key as? DerivedKey {
2326
- if let derivedValue = value as? DerivedValue {
2327
- result[derivedKey] = derivedValue
2328
- continue
2329
- }
2330
- }
2331
-
2332
- // Either the key or the value wasn't of the appropriate derived
2333
- // type. Fail.
2334
- return nil
2310
+ for (k, v) in source {
2311
+ guard let k1 = k as? DerivedKey, let v1 = v as? DerivedValue
2312
+ else { return nil }
2313
+ result[k1] = v1
2335
2314
}
2336
2315
return result
2337
2316
}
2338
2317
2318
+ #if _runtime(_ObjC)
2339
2319
/// Implements an unconditional downcast that involves bridging.
2340
2320
///
2341
2321
/// - Precondition: At least one of `SwiftKey` or `SwiftValue` is a bridged value
@@ -2417,30 +2397,7 @@ public func _dictionaryBridgeFromObjectiveCConditional<
2417
2397
}
2418
2398
return result
2419
2399
}
2420
- #else
2421
-
2422
- public func _dictionaryUpCast<DerivedKey, DerivedValue, BaseKey, BaseValue>(
2423
- _ source: Dictionary<DerivedKey, DerivedValue>
2424
- ) -> Dictionary<BaseKey, BaseValue> {
2425
- fatalError("_dictionaryUpCast is unimplemented")
2426
- }
2427
-
2428
- public func _dictionaryDownCast<BaseKey, BaseValue, DerivedKey, DerivedValue>(
2429
- _ source: Dictionary<BaseKey, BaseValue>
2430
- ) -> Dictionary<DerivedKey, DerivedValue> {
2431
- fatalError("_dictionaryDownCast is unimplemented")
2432
- }
2433
-
2434
- public func _dictionaryDownCastConditional<
2435
- BaseKey, BaseValue, DerivedKey, DerivedValue
2436
- >(
2437
- _ source: Dictionary<BaseKey, BaseValue>
2438
- ) -> Dictionary<DerivedKey, DerivedValue>? {
2439
- fatalError("_dictionaryDownCastConditional is unimplemented")
2440
- }
2441
-
2442
2400
#endif
2443
-
2444
2401
//===--- APIs templated for Dictionary and Set ----------------------------===//
2445
2402
2446
2403
%{
0 commit comments