Skip to content

Commit 1b6b69d

Browse files
committed
- Instrument _SwiftValue to understand values that can be returned by as AnyObject casts on Darwin, and move all code back to _SwiftValue.store/fetch.
1 parent b35d9c4 commit 1b6b69d

File tree

6 files changed

+46
-9
lines changed

6 files changed

+46
-9
lines changed

Foundation/Bridging.swift

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ public protocol _StructBridgeable {
1616
func _bridgeToAny() -> Any
1717
}
1818

19+
fileprivate protocol Unwrappable {
20+
func unwrap() -> Any?
21+
}
22+
23+
extension Optional: Unwrappable {
24+
func unwrap() -> Any? {
25+
return self
26+
}
27+
}
28+
1929
/// - Note: This does not exist currently on Darwin but it is the inverse correlation to the bridge types such that a
2030
/// reference type can be converted via a callout to a conversion method.
2131
public protocol _StructTypeBridgeable : _StructBridgeable {
@@ -65,7 +75,12 @@ internal final class _SwiftValue : NSObject, NSCopying {
6575

6676
static func fetch(_ object: AnyObject?) -> Any? {
6777
if let obj = object {
68-
return fetch(nonOptional: obj)
78+
let value = fetch(nonOptional: obj)
79+
if let wrapper = value as? Unwrappable, wrapper.unwrap() == nil {
80+
return nil
81+
} else {
82+
return value
83+
}
6984
}
7085
return nil
7186
}
@@ -75,6 +90,8 @@ internal final class _SwiftValue : NSObject, NSCopying {
7590
return true
7691
} else if object === kCFBooleanFalse {
7792
return false
93+
} else if type(of: object) == NSNull.self {
94+
return Optional<Any>.none as Any
7895
} else if let container = object as? _SwiftValue {
7996
return container.value
8097
} else if let val = object as? _StructBridgeable {
@@ -84,6 +101,13 @@ internal final class _SwiftValue : NSObject, NSCopying {
84101
}
85102
}
86103

104+
static func store(optional value: Any?) -> NSObject? {
105+
if let val = value {
106+
return store(val)
107+
}
108+
return nil
109+
}
110+
87111
static func store(_ value: Any?) -> NSObject? {
88112
if let val = value {
89113
return store(val)
@@ -94,8 +118,20 @@ internal final class _SwiftValue : NSObject, NSCopying {
94118
static func store(_ value: Any) -> NSObject {
95119
if let val = value as? NSObject {
96120
return val
121+
} else if let opt = value as? Unwrappable, opt.unwrap() == nil {
122+
return NSNull()
97123
} else {
98-
return (value as AnyObject) as! NSObject
124+
#if canImport(ObjectiveC)
125+
// On Darwin, this can be a native (ObjC) _SwiftValue.
126+
let boxed = (value as AnyObject)
127+
if !(boxed is NSObject) {
128+
return _SwiftValue(value) // Do not emit native boxes — wrap them in Swift Foundation boxes instead.
129+
} else {
130+
return boxed as! NSObject
131+
}
132+
#else
133+
return (value as AnyObject) as! NSObject
134+
#endif
99135
}
100136
}
101137

Foundation/NSArray.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ open class NSArray : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCo
337337
} else {
338338
let val1 = object(at: idx)
339339
let val2 = otherArray[idx]
340-
if !((val1 as AnyObject) as! NSObject).isEqual(val2 as AnyObject) {
340+
if !_SwiftValue.store(val1).isEqual(_SwiftValue.store(val2)) {
341341
return false
342342
}
343343
}

Foundation/NSDictionary.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,9 +396,10 @@ open class NSDictionary : NSObject, NSCopying, NSMutableCopying, NSSecureCoding,
396396
return false
397397
}
398398
} else {
399-
let otherBridgeable = otherDictionary[key as! AnyHashable]
400-
let bridgeable = object(forKey: key)!
401-
if !((otherBridgeable as AnyObject) as! NSObject).isEqual(bridgeable as AnyObject) {
399+
let otherBridgeable = otherDictionary[key as! AnyHashable]
400+
let bridgeable = object(forKey: key)!
401+
let equal = _SwiftValue.store(optional: otherBridgeable)?.isEqual(_SwiftValue.store(bridgeable))
402+
if equal != true {
402403
return false
403404
}
404405
}

Foundation/NSKeyedArchiver.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ open class NSKeyedArchiver : NSCoder {
597597
object = _replacementObject(objv)
598598

599599
// bridge value types
600-
object = object as AnyObject
600+
object = _SwiftValue.store(object)
601601

602602
objectRef = _referenceObject(object, conditional: conditional)
603603
guard let unwrappedObjectRef = objectRef else {

Foundation/NSKeyedUnarchiver.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ open class NSKeyedUnarchiver : NSCoder {
483483
_cacheObject(object!, forReference: objectRef as! _NSKeyedArchiverUID)
484484
}
485485
} else {
486-
object = dereferencedObject as AnyObject
486+
object = _SwiftValue.store(dereferencedObject)
487487
}
488488

489489
return _replacementObject(object)

Foundation/NSSet.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ open class NSSet : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCodi
4646
super.init()
4747
let buffer = UnsafeBufferPointer(start: objects, count: cnt)
4848
for obj in buffer {
49-
_storage.insert(obj as! NSObject)
49+
_storage.insert(_SwiftValue.store(obj))
5050
}
5151
}
5252

0 commit comments

Comments
 (0)