Skip to content

Commit 4b625a3

Browse files
authored
Merge pull request #19006 from DougGregor/error-bridging-integer-type
[Foundation] Collapse (SignedInteger|UnsignedInteger) reqts into FixedWidthInteger
2 parents 836ad07 + f64d5db commit 4b625a3

File tree

5 files changed

+108
-42
lines changed

5 files changed

+108
-42
lines changed

stdlib/public/SDK/Foundation/NSError.swift

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -162,17 +162,34 @@ public extension CustomNSError {
162162
}
163163
}
164164

165-
extension CustomNSError where Self: RawRepresentable, Self.RawValue: SignedInteger {
166-
// The error code of Error with integral raw values is the raw value.
167-
public var errorCode: Int {
168-
return numericCast(self.rawValue)
165+
/// Convert an arbitrary binary integer to an Int, reinterpreting signed
166+
/// -> unsigned if needed but trapping if the result is otherwise not
167+
/// expressible.
168+
func unsafeBinaryIntegerToInt<T: BinaryInteger>(_ value: T) -> Int {
169+
if T.isSigned {
170+
return numericCast(value)
171+
}
172+
173+
let uintValue: UInt = numericCast(value)
174+
return Int(bitPattern: uintValue)
175+
}
176+
177+
/// Convert from an Int to an arbitrary binary integer, reinterpreting signed ->
178+
/// unsigned if needed but trapping if the result is otherwise not expressible.
179+
func unsafeBinaryIntegerFromInt<T: BinaryInteger>(_ value: Int) -> T {
180+
if T.isSigned {
181+
return numericCast(value)
169182
}
183+
184+
let uintValue = UInt(bitPattern: value)
185+
return numericCast(uintValue)
170186
}
171187

172-
extension CustomNSError where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
188+
extension CustomNSError
189+
where Self: RawRepresentable, Self.RawValue: FixedWidthInteger {
173190
// The error code of Error with integral raw values is the raw value.
174191
public var errorCode: Int {
175-
return numericCast(self.rawValue)
192+
return unsafeBinaryIntegerToInt(self.rawValue)
176193
}
177194
}
178195

@@ -185,13 +202,7 @@ public extension Error where Self : CustomNSError {
185202
}
186203

187204
public extension Error where Self: CustomNSError, Self: RawRepresentable,
188-
Self.RawValue: SignedInteger {
189-
/// Default implementation for customized NSErrors.
190-
var _code: Int { return self.errorCode }
191-
}
192-
193-
public extension Error where Self: CustomNSError, Self: RawRepresentable,
194-
Self.RawValue: UnsignedInteger {
205+
Self.RawValue: FixedWidthInteger {
195206
/// Default implementation for customized NSErrors.
196207
var _code: Int { return self.errorCode }
197208
}
@@ -384,7 +395,7 @@ extension _BridgedNSError {
384395
public var _domain: String { return Self._nsErrorDomain }
385396
}
386397

387-
extension _BridgedNSError where Self.RawValue: SignedInteger {
398+
extension _BridgedNSError where Self.RawValue: FixedWidthInteger {
388399
public var _code: Int { return Int(rawValue) }
389400

390401
public init?(_bridgedNSError: NSError) {
@@ -398,22 +409,6 @@ extension _BridgedNSError where Self.RawValue: SignedInteger {
398409
public var hashValue: Int { return _code }
399410
}
400411

401-
extension _BridgedNSError where Self.RawValue: UnsignedInteger {
402-
public var _code: Int {
403-
return Int(bitPattern: UInt(rawValue))
404-
}
405-
406-
public init?(_bridgedNSError: NSError) {
407-
if _bridgedNSError.domain != Self._nsErrorDomain {
408-
return nil
409-
}
410-
411-
self.init(rawValue: RawValue(UInt(bitPattern: _bridgedNSError.code)))
412-
}
413-
414-
public var hashValue: Int { return _code }
415-
}
416-
417412
/// Describes a bridged error that stores the underlying NSError, so
418413
/// it can be queried.
419414
public protocol _BridgedStoredNSError :
@@ -446,14 +441,14 @@ internal func _stringDictToAnyHashableDict(_ input: [String : Any])
446441
/// Various helper implementations for _BridgedStoredNSError
447442
extension _BridgedStoredNSError {
448443
public var code: Code {
449-
return Code(rawValue: numericCast(_nsError.code))!
444+
return Code(rawValue: unsafeBinaryIntegerFromInt(_nsError.code))!
450445
}
451446

452447
/// Initialize an error within this domain with the given ``code``
453448
/// and ``userInfo``.
454449
public init(_ code: Code, userInfo: [String : Any] = [:]) {
455450
self.init(_nsError: NSError(domain: Self.errorDomain,
456-
code: numericCast(code.rawValue),
451+
code: unsafeBinaryIntegerToInt(code.rawValue),
457452
userInfo: _stringDictToAnyHashableDict(userInfo)))
458453
}
459454

stdlib/public/core/ErrorType.swift

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,14 @@ extension Error {
211211
}
212212
}
213213

214-
extension Error where Self: RawRepresentable, Self.RawValue: SignedInteger {
214+
extension Error where Self: RawRepresentable, Self.RawValue: FixedWidthInteger {
215215
// The error code of Error with integral raw values is the raw value.
216216
public var _code: Int {
217-
return numericCast(self.rawValue)
218-
}
219-
}
217+
if Self.RawValue.isSigned {
218+
return numericCast(self.rawValue)
219+
}
220220

221-
extension Error where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
222-
// The error code of Error with integral raw values is the raw value.
223-
public var _code: Int {
224-
return numericCast(self.rawValue)
221+
let uintValue: UInt = numericCast(self.rawValue)
222+
return Int(bitPattern: uintValue)
225223
}
226224
}

test/stdlib/Error.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: %target-run-simple-swift
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -o %t/Error -DPTR_SIZE_%target-ptrsize -module-name main %s
3+
// RUN: %target-run %t/Error
24
// REQUIRES: executable_test
35

46
import StdlibUnittest
@@ -143,5 +145,20 @@ ErrorTests.test("existential in lvalue") {
143145
expectEqual(0, LifetimeTracked.instances)
144146
}
145147

148+
enum UnsignedError: UInt, Error {
149+
#if PTR_SIZE_64
150+
case negativeOne = 0xFFFFFFFFFFFFFFFF
151+
#elseif PTR_SIZE_32
152+
case negativeOne = 0xFFFFFFFF
153+
#else
154+
#error ("Unknown pointer size")
155+
#endif
156+
}
157+
158+
ErrorTests.test("unsigned raw value") {
159+
let negOne: Error = UnsignedError.negativeOne
160+
expectEqual(-1, negOne._code)
161+
}
162+
146163
runAllTests()
147164

test/stdlib/ErrorBridged.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: %target-run-simple-swift-swift3
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -o %t/ErrorBridged -DPTR_SIZE_%target-ptrsize -module-name main -swift-version 3 %s
3+
// RUN: %target-run %t/ErrorBridged
24
// REQUIRES: executable_test
35
// REQUIRES: objc_interop
46

@@ -608,6 +610,14 @@ enum DefaultCustomizedError3 : UInt, CustomNSError {
608610
case bad = 9
609611
case worse = 115
610612

613+
#if PTR_SIZE_64
614+
case dreadful = 0xFFFFFFFFFFFFFFFF
615+
#elseif PTR_SIZE_32
616+
case dreadful = 0xFFFFFFFF
617+
#else
618+
#error ("Unknown pointer size")
619+
#endif
620+
611621
static var errorDomain: String {
612622
return "customized3"
613623
}
@@ -623,6 +633,7 @@ ErrorBridgingTests.test("Default-customized via CustomNSError") {
623633
expectEqual(1, (DefaultCustomizedError1.worse as NSError).code)
624634
expectEqual(13, (DefaultCustomizedError2.worse as NSError).code)
625635
expectEqual(115, (DefaultCustomizedError3.worse as NSError).code)
636+
expectEqual(-1, (DefaultCustomizedError3.dreadful as NSError).code)
626637
expectEqual("main.DefaultCustomizedError1", (DefaultCustomizedError1.worse as NSError).domain)
627638
expectEqual("customized3", (DefaultCustomizedError3.worse as NSError).domain)
628639
expectEqual("main.DefaultCustomizedParent.ChildError", (DefaultCustomizedParent.ChildError.foo as NSError).domain)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_nested
3+
// RUN: %target-run %target-swift-reflection-test %t/reflect_nested 2>&1 | %FileCheck %s --check-prefix=CHECK-%target-ptrsize
4+
// REQUIRES: objc_interop
5+
// REQUIRES: executable_test
6+
7+
import SwiftReflectionTest
8+
9+
class OuterGeneric<T> {
10+
class Inner {
11+
class Innermost<U> {
12+
var x: T
13+
var y: U
14+
15+
init(x: T, y: U) {
16+
self.x = x
17+
self.y = y
18+
}
19+
}
20+
}
21+
}
22+
23+
var obj = OuterGeneric.Inner.Innermost(x: 17, y: "hello")
24+
25+
reflect(object: obj)
26+
27+
// CHECK-64: Reflecting an object.
28+
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
29+
// CHECK-64: Type reference:
30+
// CHECK-64: (bound_generic_class reflect_nested.OuterGeneric.Inner.Innermost
31+
// CHECK-64-NEXT: (struct Swift.Int)
32+
// CHECK-64-NEXT: (struct Swift.String)
33+
34+
// CHECK-32: Reflecting an object.
35+
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
36+
// CHECK-32: Type reference:
37+
// CHECK-32: (bound_generic_class reflect_nested.OuterGeneric.Inner.Innermost
38+
// CHECK-32-NEXT: (struct Swift.Int)
39+
// CHECK-32-NEXT: (struct Swift.String)
40+
41+
doneReflecting()
42+
43+
// CHECK-64: Done.
44+
45+
// CHECK-32: Done.

0 commit comments

Comments
 (0)