diff --git a/Foundation/AffineTransform.swift b/Foundation/AffineTransform.swift index b5d5d20d1e..5f3864b584 100644 --- a/Foundation/AffineTransform.swift +++ b/Foundation/AffineTransform.swift @@ -476,7 +476,7 @@ open class NSAffineTransform : NSObject, NSCopying, NSSecureCoding { } } -extension AffineTransform : _ObjectTypeBridgeable { +extension AffineTransform : _ObjectiveCBridgeable { public static func _isBridgedToObjectiveC() -> Bool { return true } diff --git a/Foundation/Array.swift b/Foundation/Array.swift index 23d2662845..1b482c17b0 100644 --- a/Foundation/Array.swift +++ b/Foundation/Array.swift @@ -7,7 +7,7 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // -extension Array : _ObjectTypeBridgeable { +extension Array : _ObjectiveCBridgeable { public typealias _ObjectType = NSArray public func _bridgeToObjectiveC() -> _ObjectType { diff --git a/Foundation/Bridging.swift b/Foundation/Bridging.swift index 0f60487c99..ad0114ba2a 100644 --- a/Foundation/Bridging.swift +++ b/Foundation/Bridging.swift @@ -12,29 +12,10 @@ import CoreFoundation -// Support protocols for casting -public protocol _ObjectBridgeable { - func _bridgeToAnyObject() -> AnyObject -} - public protocol _StructBridgeable { func _bridgeToAny() -> Any } -/// - Note: This is a similar interface to the _ObjectiveCBridgeable protocol -public protocol _ObjectTypeBridgeable : _ObjectBridgeable { - associatedtype _ObjectType : AnyObject - - func _bridgeToObjectiveC() -> _ObjectType - - static func _forceBridgeFromObjectiveC(_ source: _ObjectType, result: inout Self?) - - @discardableResult - static func _conditionallyBridgeFromObjectiveC(_ source: _ObjectType, result: inout Self?) -> Bool - - static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectType?) -> Self -} - /// - Note: This does not exist currently on Darwin but it is the inverse correlation to the bridge types such that a /// reference type can be converted via a callout to a conversion method. public protocol _StructTypeBridgeable : _StructBridgeable { @@ -44,7 +25,7 @@ public protocol _StructTypeBridgeable : _StructBridgeable { } // Default adoption of the type specific variants to the Any variant -extension _ObjectTypeBridgeable { +extension _ObjectiveCBridgeable { public func _bridgeToAnyObject() -> AnyObject { return _bridgeToObjectiveC() } @@ -74,8 +55,8 @@ internal protocol _NSBridgeable { /// - Note: This is an internal boxing value for containing abstract structures -internal final class _SwiftValue : NSObject, NSCopying { - internal private(set) var value: Any +internal final class _SwiftValue : NSObject, NSCopying, _NSSwiftValue { + public private(set) var value: Any static func fetch(_ object: AnyObject?) -> Any? { if let obj = object { @@ -108,10 +89,8 @@ internal final class _SwiftValue : NSObject, NSCopying { static func store(_ value: Any) -> NSObject { if let val = value as? NSObject { return val - } else if let val = value as? _ObjectBridgeable { - return val._bridgeToAnyObject() as! NSObject } else { - return _SwiftValue(value) + return (value as AnyObject) as! NSObject } } @@ -144,4 +123,6 @@ internal final class _SwiftValue : NSObject, NSCopying { public func copy(with zone: NSZone?) -> Any { return _SwiftValue(value) } + + public static let null: AnyObject = NSNull() } diff --git a/Foundation/Calendar.swift b/Foundation/Calendar.swift index 79dc7682a7..893971bdcb 100644 --- a/Foundation/Calendar.swift +++ b/Foundation/Calendar.swift @@ -1163,7 +1163,7 @@ extension Calendar : CustomDebugStringConvertible, CustomStringConvertible, Cust } } -extension Calendar: _ObjectTypeBridgeable { +extension Calendar: _ObjectiveCBridgeable { public typealias _ObjectType = NSCalendar @_semantics("convertToObjectiveC") diff --git a/Foundation/CharacterSet.swift b/Foundation/CharacterSet.swift index 664423ace9..7b8c233f48 100644 --- a/Foundation/CharacterSet.swift +++ b/Foundation/CharacterSet.swift @@ -481,7 +481,7 @@ public struct CharacterSet : ReferenceConvertible, Equatable, Hashable, SetAlgeb // MARK: Objective-C Bridging -extension CharacterSet : _ObjectTypeBridgeable { +extension CharacterSet : _ObjectiveCBridgeable { public static func _isBridgedToObjectiveC() -> Bool { return true } diff --git a/Foundation/Data.swift b/Foundation/Data.swift index 562e35cd13..3ef400ca03 100644 --- a/Foundation/Data.swift +++ b/Foundation/Data.swift @@ -1893,13 +1893,7 @@ extension Data { /// Provides bridging functionality for struct Data to class NSData and vice-versa. -#if DEPLOYMENT_RUNTIME_SWIFT -internal typealias DataBridgeType = _ObjectTypeBridgeable -#else -internal typealias DataBridgeType = _ObjectiveCBridgeable -#endif - -extension Data : DataBridgeType { +extension Data : _ObjectiveCBridgeable { @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> NSData { return _backing.bridgedReference(_sliceRange) diff --git a/Foundation/Date.swift b/Foundation/Date.swift index 8d948cdcc1..d1b2d99ec5 100644 --- a/Foundation/Date.swift +++ b/Foundation/Date.swift @@ -230,7 +230,7 @@ extension Date : CustomDebugStringConvertible, CustomStringConvertible, CustomRe } } -extension Date : _ObjectTypeBridgeable { +extension Date : _ObjectiveCBridgeable { @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> NSDate { return NSDate(timeIntervalSinceReferenceDate: _time) diff --git a/Foundation/DateComponents.swift b/Foundation/DateComponents.swift index e65793ddf1..5faa341cc6 100644 --- a/Foundation/DateComponents.swift +++ b/Foundation/DateComponents.swift @@ -352,7 +352,7 @@ extension DateComponents : CustomStringConvertible, CustomDebugStringConvertible // MARK: - Bridging -extension DateComponents : _ObjectTypeBridgeable { +extension DateComponents : _ObjectiveCBridgeable { public static func _isBridgedToObjectiveC() -> Bool { return true } diff --git a/Foundation/DateInterval.swift b/Foundation/DateInterval.swift index 0d22b7a783..c3d2746ee1 100644 --- a/Foundation/DateInterval.swift +++ b/Foundation/DateInterval.swift @@ -187,7 +187,7 @@ extension DateInterval : CustomStringConvertible, CustomDebugStringConvertible, } } -extension DateInterval : _ObjectTypeBridgeable { +extension DateInterval : _ObjectiveCBridgeable { public static func _isBridgedToObjectiveC() -> Bool { return true } diff --git a/Foundation/Dictionary.swift b/Foundation/Dictionary.swift index 8d8981b505..3e79125965 100644 --- a/Foundation/Dictionary.swift +++ b/Foundation/Dictionary.swift @@ -9,7 +9,7 @@ import CoreFoundation -extension Dictionary : _ObjectTypeBridgeable { +extension Dictionary : _ObjectiveCBridgeable { public typealias _ObjectType = NSDictionary public func _bridgeToObjectiveC() -> _ObjectType { diff --git a/Foundation/IndexPath.swift b/Foundation/IndexPath.swift index 3da5d9eec4..7024e6309f 100644 --- a/Foundation/IndexPath.swift +++ b/Foundation/IndexPath.swift @@ -774,13 +774,7 @@ extension IndexPath : CustomStringConvertible, CustomDebugStringConvertible, Cus } } -#if DEPLOYMENT_RUNTIME_SWIFT -internal typealias IndexPathBridgeType = _ObjectTypeBridgeable -#else -internal typealias IndexPathBridgeType = _ObjectiveCBridgeable -#endif - -extension IndexPath : IndexPathBridgeType { +extension IndexPath : _ObjectiveCBridgeable { public static func _getObjectiveCType() -> Any.Type { return NSIndexPath.self } diff --git a/Foundation/IndexSet.swift b/Foundation/IndexSet.swift index 619353f8f5..0027652ed5 100644 --- a/Foundation/IndexSet.swift +++ b/Foundation/IndexSet.swift @@ -790,13 +790,7 @@ private func _toNSRange(_ r: Range) -> NSRange { return NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound) } -#if DEPLOYMENT_RUNTIME_SWIFT -internal typealias IndexSetBridgeType = _ObjectTypeBridgeable -#else -internal typealias IndexSetBridgeType = _ObjectiveCBridgeable -#endif - -extension IndexSet : IndexSetBridgeType { +extension IndexSet : _ObjectiveCBridgeable { public static func _getObjectiveCType() -> Any.Type { return NSIndexSet.self } diff --git a/Foundation/JSONSerialization.swift b/Foundation/JSONSerialization.swift index d01d80d9bf..78b62bc9dd 100644 --- a/Foundation/JSONSerialization.swift +++ b/Foundation/JSONSerialization.swift @@ -62,10 +62,12 @@ open class JSONSerialization : NSObject { return true } - if obj is String || obj is NSNull || obj is Int || obj is Bool || obj is UInt || - obj is Int8 || obj is Int16 || obj is Int32 || obj is Int64 || - obj is UInt8 || obj is UInt16 || obj is UInt32 || obj is UInt64 { - return true + if !(obj is _NSNumberCastingWithoutBridging) { + if obj is String || obj is NSNull || obj is Int || obj is Bool || obj is UInt || + obj is Int8 || obj is Int16 || obj is Int32 || obj is Int64 || + obj is UInt8 || obj is UInt16 || obj is UInt32 || obj is UInt64 { + return true + } } // object is a Double and is not NaN or infinity @@ -315,12 +317,19 @@ private struct JSONWriter { self.writer = writer } - mutating func serializeJSON(_ obj: Any?) throws { + mutating func serializeJSON(_ object: Any?) throws { + + var toSerialize = object - guard let obj = obj else { + if let number = toSerialize as? _NSNumberCastingWithoutBridging { + toSerialize = number._swiftValueOfOptimalType + } + + guard let obj = toSerialize else { try serializeNull() return } + // For better performance, the most expensive conditions to evaluate should be last. switch (obj) { case let str as String: diff --git a/Foundation/Locale.swift b/Foundation/Locale.swift index 1544767d53..c378ae2fc1 100644 --- a/Foundation/Locale.swift +++ b/Foundation/Locale.swift @@ -439,7 +439,7 @@ public struct Locale : CustomStringConvertible, CustomDebugStringConvertible, Ha } -extension Locale : _ObjectTypeBridgeable { +extension Locale : _ObjectiveCBridgeable { public static func _isBridgedToObjectiveC() -> Bool { return true } diff --git a/Foundation/Measurement.swift b/Foundation/Measurement.swift index cca183d03f..f5b5a16175 100644 --- a/Foundation/Measurement.swift +++ b/Foundation/Measurement.swift @@ -206,14 +206,8 @@ extension Measurement { // Implementation note: similar to NSArray, NSDictionary, etc., NSMeasurement's import as an ObjC generic type is suppressed by the importer. Eventually we will need a more general purpose mechanism to correctly import generic types. -#if DEPLOYMENT_RUNTIME_SWIFT -internal typealias MeasurementBridgeType = _ObjectTypeBridgeable -#else -internal typealias MeasurementBridgeType = _ObjectiveCBridgeable -#endif - @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) -extension Measurement : MeasurementBridgeType { +extension Measurement : _ObjectiveCBridgeable { @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> NSMeasurement { return NSMeasurement(doubleValue: value, unit: unit) diff --git a/Foundation/NSArray.swift b/Foundation/NSArray.swift index eb4e1896ef..e2d2a1df21 100644 --- a/Foundation/NSArray.swift +++ b/Foundation/NSArray.swift @@ -334,13 +334,12 @@ open class NSArray : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCo if val1 != val2 { return false } - } else if let val1 = object(at: idx) as? _ObjectBridgeable, - let val2 = otherArray[idx] as? _ObjectBridgeable { - if !(val1._bridgeToAnyObject() as! NSObject).isEqual(val2._bridgeToAnyObject()) { + } else { + let val1 = object(at: idx) + let val2 = otherArray[idx] + if !((val1 as AnyObject) as! NSObject).isEqual(val2 as AnyObject) { return false } - } else { - return false } } diff --git a/Foundation/NSDecimalNumber.swift b/Foundation/NSDecimalNumber.swift index 06d4aa45b0..5a7c9851d1 100644 --- a/Foundation/NSDecimalNumber.swift +++ b/Foundation/NSDecimalNumber.swift @@ -297,28 +297,28 @@ open class NSDecimalNumber : NSNumber { // return 'd' for double open override var int8Value: Int8 { - return Int8(decimal.doubleValue) + return Int8(exactly: decimal.doubleValue) ?? 0 as Int8 } open override var uint8Value: UInt8 { - return UInt8(decimal.doubleValue) + return UInt8(exactly: decimal.doubleValue) ?? 0 as UInt8 } open override var int16Value: Int16 { - return Int16(decimal.doubleValue) + return Int16(exactly: decimal.doubleValue) ?? 0 as Int16 } open override var uint16Value: UInt16 { - return UInt16(decimal.doubleValue) + return UInt16(exactly: decimal.doubleValue) ?? 0 as UInt16 } open override var int32Value: Int32 { - return Int32(decimal.doubleValue) + return Int32(exactly: decimal.doubleValue) ?? 0 as Int32 } open override var uint32Value: UInt32 { - return UInt32(decimal.doubleValue) + return UInt32(exactly: decimal.doubleValue) ?? 0 as UInt32 } open override var int64Value: Int64 { - return Int64(decimal.doubleValue) + return Int64(exactly: decimal.doubleValue) ?? 0 as Int64 } open override var uint64Value: UInt64 { - return UInt64(decimal.doubleValue) + return UInt64(exactly: decimal.doubleValue) ?? 0 as UInt64 } open override var floatValue: Float { return Float(decimal.doubleValue) @@ -330,10 +330,10 @@ open class NSDecimalNumber : NSNumber { return !decimal.isZero } open override var intValue: Int { - return Int(decimal.doubleValue) + return Int(exactly: decimal.doubleValue) ?? 0 as Int } open override var uintValue: UInt { - return UInt(decimal.doubleValue) + return UInt(exactly: decimal.doubleValue) ?? 0 as UInt } open override func isEqual(_ value: Any?) -> Bool { @@ -341,6 +341,9 @@ open class NSDecimalNumber : NSNumber { return self.decimal == other.decimal } + override var _swiftValueOfOptimalType: Any { + return decimal + } } // return an approximate double value diff --git a/Foundation/NSDictionary.swift b/Foundation/NSDictionary.swift index 77bdcdef7f..deae11a7ab 100644 --- a/Foundation/NSDictionary.swift +++ b/Foundation/NSDictionary.swift @@ -395,13 +395,12 @@ open class NSDictionary : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, if otherValue != value { return false } - } else if let otherBridgeable = otherDictionary[key as! AnyHashable] as? _ObjectBridgeable, - let bridgeable = object(forKey: key)! as? _ObjectBridgeable { - if !(otherBridgeable._bridgeToAnyObject() as! NSObject).isEqual(bridgeable._bridgeToAnyObject()) { + } else { + let otherBridgeable = otherDictionary[key as! AnyHashable] + let bridgeable = object(forKey: key)! + if !((otherBridgeable as AnyObject) as! NSObject).isEqual(bridgeable as AnyObject) { return false } - } else { - return false } } diff --git a/Foundation/NSError.swift b/Foundation/NSError.swift index 3ea17e227d..ddc6bf0da5 100644 --- a/Foundation/NSError.swift +++ b/Foundation/NSError.swift @@ -402,7 +402,7 @@ extension CFError : Error { /// An internal protocol to represent Swift error enums that map to standard /// Cocoa NSError domains. -public protocol _ObjectTypeBridgeableError : Error { +public protocol _ObjectiveCBridgeableError : Error { /// Produce a value of the error type corresponding to the given NSError, /// or return nil if it cannot be bridged. init?(_bridgedNSError: NSError) @@ -472,15 +472,15 @@ public extension __BridgedNSError where Self: RawRepresentable, Self.RawValue: U /// NSError domain. /// /// This protocol is used primarily to generate the conformance to -/// _ObjectTypeBridgeableError for such an enum. -public protocol _BridgedNSError : __BridgedNSError, RawRepresentable, _ObjectTypeBridgeableError, Hashable { +/// _ObjectiveCBridgeableError for such an enum. +public protocol _BridgedNSError : __BridgedNSError, RawRepresentable, _ObjectiveCBridgeableError, Hashable { /// The NSError domain to which this type is bridged. static var _nsErrorDomain: String { get } } /// Describes a bridged error that stores the underlying NSError, so /// it can be queried. -public protocol _BridgedStoredNSError : __BridgedNSError, _ObjectTypeBridgeableError, CustomNSError, Hashable { +public protocol _BridgedStoredNSError : __BridgedNSError, _ObjectiveCBridgeableError, CustomNSError, Hashable { /// The type of an error code. associatedtype Code: _ErrorCodeProtocol @@ -1378,3 +1378,35 @@ extension POSIXError { /// Interface output queue is full. public static var EQFULL: POSIXError.Code { return .EQFULL } } + +enum UnknownNSError: Error { + case missingError +} + +public // COMPILER_INTRINSIC +func _convertNSErrorToError(_ error: NSError?) -> Error { + return error ?? UnknownNSError.missingError +} + +public // COMPILER_INTRINSIC +func _convertErrorToNSError(_ error: Error) -> NSError { + if let object = _extractDynamicValue(error as Any) { + return unsafeBitCast(object, to: NSError.self) + } else { + let domain: String + let code: Int + let userInfo: [String: Any] + + if let error = error as? CustomNSError { + domain = type(of: error).errorDomain + code = error.errorCode + userInfo = error.errorUserInfo + } else { + domain = "SwiftError" + code = 0 + userInfo = (_swift_Foundation_getErrorDefaultUserInfo(error) as? [String : Any]) ?? [:] + } + + return NSError(domain: domain, code: code, userInfo: userInfo) + } +} diff --git a/Foundation/NSKeyedArchiver.swift b/Foundation/NSKeyedArchiver.swift index 6df2ae1867..2efcec99f3 100644 --- a/Foundation/NSKeyedArchiver.swift +++ b/Foundation/NSKeyedArchiver.swift @@ -597,9 +597,7 @@ open class NSKeyedArchiver : NSCoder { object = _replacementObject(objv) // bridge value types - if let bridgedObject = object as? _ObjectBridgeable { - object = bridgedObject._bridgeToAnyObject() - } + object = object as AnyObject objectRef = _referenceObject(object, conditional: conditional) guard let unwrappedObjectRef = objectRef else { diff --git a/Foundation/NSKeyedUnarchiver.swift b/Foundation/NSKeyedUnarchiver.swift index d75a664136..2acd88fb1a 100644 --- a/Foundation/NSKeyedUnarchiver.swift +++ b/Foundation/NSKeyedUnarchiver.swift @@ -483,12 +483,7 @@ open class NSKeyedUnarchiver : NSCoder { _cacheObject(object!, forReference: objectRef as! _NSKeyedArchiverUID) } } else { - // reference to a non-container object - if let bridgedObject = dereferencedObject as? _ObjectBridgeable { - object = bridgedObject._bridgeToAnyObject() - } else { - object = dereferencedObject - } + object = dereferencedObject as AnyObject } return _replacementObject(object) diff --git a/Foundation/NSNumber.swift b/Foundation/NSNumber.swift index 1d67526a3a..755b82888f 100644 --- a/Foundation/NSNumber.swift +++ b/Foundation/NSNumber.swift @@ -32,7 +32,7 @@ internal let kCFNumberSInt128Type = CFNumberType(rawValue: 17)! internal let kCFNumberSInt128Type: CFNumberType = 17 #endif -extension Int8 : _ObjectTypeBridgeable { +extension Int8 : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.int8Value @@ -70,7 +70,7 @@ extension Int8 : _ObjectTypeBridgeable { } } -extension UInt8 : _ObjectTypeBridgeable { +extension UInt8 : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.uint8Value @@ -108,7 +108,7 @@ extension UInt8 : _ObjectTypeBridgeable { } } -extension Int16 : _ObjectTypeBridgeable { +extension Int16 : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.int16Value @@ -146,7 +146,7 @@ extension Int16 : _ObjectTypeBridgeable { } } -extension UInt16 : _ObjectTypeBridgeable { +extension UInt16 : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.uint16Value @@ -184,7 +184,7 @@ extension UInt16 : _ObjectTypeBridgeable { } } -extension Int32 : _ObjectTypeBridgeable { +extension Int32 : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.int32Value @@ -222,7 +222,7 @@ extension Int32 : _ObjectTypeBridgeable { } } -extension UInt32 : _ObjectTypeBridgeable { +extension UInt32 : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.uint32Value @@ -260,7 +260,7 @@ extension UInt32 : _ObjectTypeBridgeable { } } -extension Int64 : _ObjectTypeBridgeable { +extension Int64 : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.int64Value @@ -298,7 +298,7 @@ extension Int64 : _ObjectTypeBridgeable { } } -extension UInt64 : _ObjectTypeBridgeable { +extension UInt64 : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.uint64Value @@ -336,7 +336,7 @@ extension UInt64 : _ObjectTypeBridgeable { } } -extension Int : _ObjectTypeBridgeable { +extension Int : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.intValue @@ -374,7 +374,7 @@ extension Int : _ObjectTypeBridgeable { } } -extension UInt : _ObjectTypeBridgeable { +extension UInt : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.uintValue @@ -412,7 +412,7 @@ extension UInt : _ObjectTypeBridgeable { } } -extension Float : _ObjectTypeBridgeable { +extension Float : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.floatValue @@ -461,7 +461,7 @@ extension Float : _ObjectTypeBridgeable { } } -extension Double : _ObjectTypeBridgeable { +extension Double : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.doubleValue @@ -512,7 +512,7 @@ extension Double : _ObjectTypeBridgeable { } } -extension Bool : _ObjectTypeBridgeable { +extension Bool : _ObjectiveCBridgeable { @available(swift, deprecated: 4, renamed: "init(truncating:)") public init(_ number: NSNumber) { self = number.boolValue @@ -584,6 +584,13 @@ open class NSNumber : NSValue { } open override func isEqual(_ value: Any?) -> Bool { + // IMPORTANT: + // .isEqual() is invoked by the bridging machinery that gets triggered whenever you use '(-a NSNumber value-) as{,?,!} Int', so using a refutable pattern ('case let other as NSNumber') below will cause an infinite loop if value is an Int, and similarly for other types we can bridge to. + // To prevent this, _this check must come first._ If you change it, _do not use the 'as' operator_ or any of its variants _unless_ you know that value _is_ actually a NSNumber to avoid infinite loops. ('is' is fine.) + if let value = value, value is NSNumber { + return compare(value as! NSNumber) == .orderedSame + } + switch value { case let other as Int: return intValue == other @@ -591,8 +598,6 @@ open class NSNumber : NSValue { return doubleValue == other case let other as Bool: return boolValue == other - case let other as NSNumber: - return compare(other) == .orderedSame default: return false } @@ -645,7 +650,12 @@ open class NSNumber : NSValue { case kCFNumberFloat64Type: return doubleValue case kCFNumberSInt128Type: - return int128Value + // If the high portion is 0, return just the low portion as a UInt64, which reasonably fixes trying to roundtrip UInt.max and UInt64.max. + if int128Value.high == 0 { + return int128Value.low + } else { + return int128Value + } default: fatalError("unsupported CFNumberType: '\(numberType)'") } @@ -1077,3 +1087,9 @@ internal func _CFSwiftNumberGetValue(_ obj: CFTypeRef, _ valuePtr: UnsafeMutable internal func _CFSwiftNumberGetBoolValue(_ obj: CFTypeRef) -> Bool { return unsafeBitCast(obj, to: NSNumber.self).boolValue } + +protocol _NSNumberCastingWithoutBridging { + var _swiftValueOfOptimalType: Any { get } +} + +extension NSNumber: _NSNumberCastingWithoutBridging {} diff --git a/Foundation/NSSet.swift b/Foundation/NSSet.swift index 81aeaccf19..3cb2461c1c 100644 --- a/Foundation/NSSet.swift +++ b/Foundation/NSSet.swift @@ -107,7 +107,10 @@ open class NSSet : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCodi return true } - open func description(withLocale locale: Locale?) -> String { NSUnimplemented() } + open func description(withLocale locale: Locale?) -> String { + // NSUnimplemented() + return description + } override open var _cfTypeID: CFTypeID { return CFSetGetTypeID() diff --git a/Foundation/Notification.swift b/Foundation/Notification.swift index d929dbe5e3..dce3ad83ab 100644 --- a/Foundation/Notification.swift +++ b/Foundation/Notification.swift @@ -91,7 +91,7 @@ extension Notification : CustomReflectable { } -extension Notification : _ObjectTypeBridgeable { +extension Notification : _ObjectiveCBridgeable { public static func _getObjectiveCType() -> Any.Type { return NSNotification.self } diff --git a/Foundation/PersonNameComponents.swift b/Foundation/PersonNameComponents.swift index c9fc5a086a..48e57475c8 100644 --- a/Foundation/PersonNameComponents.swift +++ b/Foundation/PersonNameComponents.swift @@ -102,7 +102,7 @@ extension PersonNameComponents : CustomStringConvertible, CustomDebugStringConve } } -extension PersonNameComponents : _ObjectTypeBridgeable { +extension PersonNameComponents : _ObjectiveCBridgeable { public static func _getObjectiveCType() -> Any.Type { return NSPersonNameComponents.self } diff --git a/Foundation/Set.swift b/Foundation/Set.swift index 1db2f1048f..0eb8a5534c 100644 --- a/Foundation/Set.swift +++ b/Foundation/Set.swift @@ -9,13 +9,13 @@ import CoreFoundation -extension Set : _ObjectTypeBridgeable { +extension Set : _ObjectiveCBridgeable { public typealias _ObjectType = NSSet public func _bridgeToObjectiveC() -> _ObjectType { let buffer = UnsafeMutablePointer.allocate(capacity: count) for (idx, obj) in enumerated() { - buffer.advanced(by: idx).initialize(to: (obj as! _ObjectBridgeable)._bridgeToAnyObject()) + buffer.advanced(by: idx).initialize(to: obj as AnyObject) } let set = NSSet(objects: buffer, count: count) diff --git a/Foundation/String.swift b/Foundation/String.swift index 251f1bba2c..2b0d00d062 100644 --- a/Foundation/String.swift +++ b/Foundation/String.swift @@ -12,7 +12,7 @@ import CoreFoundation -extension String : _ObjectTypeBridgeable { +extension String : _ObjectiveCBridgeable { public typealias _ObjectType = NSString public func _bridgeToObjectiveC() -> _ObjectType { diff --git a/Foundation/URL.swift b/Foundation/URL.swift index 3cac3f6930..b704d4eb63 100644 --- a/Foundation/URL.swift +++ b/Foundation/URL.swift @@ -957,7 +957,7 @@ public struct URL : ReferenceConvertible, Equatable { } } -extension URL : _ObjectTypeBridgeable { +extension URL : _ObjectiveCBridgeable { @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> NSURL { return _url diff --git a/Foundation/URLComponents.swift b/Foundation/URLComponents.swift index 71d63eb429..6610db0738 100644 --- a/Foundation/URLComponents.swift +++ b/Foundation/URLComponents.swift @@ -395,7 +395,7 @@ extension URLQueryItem : _NSBridgeable { internal var _nsObject: NSType { return _queryItem } } -extension URLComponents : _ObjectTypeBridgeable { +extension URLComponents : _ObjectiveCBridgeable { public typealias _ObjectType = NSURLComponents public static func _getObjectiveCType() -> Any.Type { @@ -425,7 +425,7 @@ extension URLComponents : _ObjectTypeBridgeable { } } -extension URLQueryItem : _ObjectTypeBridgeable { +extension URLQueryItem : _ObjectiveCBridgeable { public typealias _ObjectType = NSURLQueryItem public static func _getObjectiveCType() -> Any.Type { diff --git a/Foundation/URLRequest.swift b/Foundation/URLRequest.swift index f0a8a4d564..2715f2ba16 100644 --- a/Foundation/URLRequest.swift +++ b/Foundation/URLRequest.swift @@ -267,7 +267,7 @@ extension URLRequest : CustomStringConvertible, CustomDebugStringConvertible, Cu } } -extension URLRequest : _ObjectTypeBridgeable { +extension URLRequest : _ObjectiveCBridgeable { public static func _getObjectiveCType() -> Any.Type { return NSURLRequest.self } diff --git a/Foundation/UUID.swift b/Foundation/UUID.swift index 9b51302912..584083e9a7 100644 --- a/Foundation/UUID.swift +++ b/Foundation/UUID.swift @@ -131,7 +131,7 @@ extension UUID : CustomReflectable { } } -extension UUID : _ObjectTypeBridgeable { +extension UUID : _ObjectiveCBridgeable { @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> NSUUID { return reference diff --git a/TestFoundation/TestJSONSerialization.swift b/TestFoundation/TestJSONSerialization.swift index eff4ea0dd4..c11f311d77 100644 --- a/TestFoundation/TestJSONSerialization.swift +++ b/TestFoundation/TestJSONSerialization.swift @@ -1198,7 +1198,8 @@ extension TestJSONSerialization { } func test_serialize_UIntMin() { - let json: [Any] = [UInt.min] + let array: [UInt] = [UInt.min] + let json = array as [Any] XCTAssertEqual(try trySerialize(json), "[\(UInt.min)]") } diff --git a/TestFoundation/TestNSKeyedArchiver.swift b/TestFoundation/TestNSKeyedArchiver.swift index 3468f83102..889a5e1853 100644 --- a/TestFoundation/TestNSKeyedArchiver.swift +++ b/TestFoundation/TestNSKeyedArchiver.swift @@ -41,7 +41,7 @@ public class NSUserClass : NSObject, NSSecureCoding { } } -public class UserClass : CustomStringConvertible, Equatable, Hashable, NSSecureCoding { +public class UserClass : NSObject, NSSecureCoding { var ivar : Int public class var supportsSecureCoding: Bool { @@ -54,24 +54,26 @@ public class UserClass : CustomStringConvertible, Equatable, Hashable, NSSecureC init(_ value: Int) { self.ivar = value + super.init() } public required init?(coder aDecoder: NSCoder) { self.ivar = aDecoder.decodeInteger(forKey: "$ivar") + super.init() } - public var description: String { + public override var description: String { get { return "UserClass \(ivar)" } } - public static func ==(lhs: UserClass, rhs: UserClass) -> Bool { - return lhs.ivar == rhs.ivar - } - - public var hashValue: Int { - return ivar + public override func isEqual(_ other: Any?) -> Bool { + guard let other = other as? UserClass else { + return false + } + + return ivar == other.ivar } }