Skip to content

Commit 4990fbd

Browse files
author
Enrico Granata
committed
In order to avoid reference cycles and repeat printing of data, stringForPrintObject maintains a list of references it has encountered and skips printing them
Bridging was causing an issue where some value types were being bridged into references and ending up randomly causing collisions which would make certain data not be printed when it should have Make it so that we only tuck away references we know are natively references for uniqueness purposes Fixes rdar://problem/27319054
1 parent fe2c2d1 commit 4990fbd

File tree

2 files changed

+69
-10
lines changed

2 files changed

+69
-10
lines changed

stdlib/public/core/DebuggerSupport.swift

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,36 @@ public enum _DebuggerSupport {
3838
}
3939
}
4040

41-
internal static func asObjectIdentifier(_ value: Any) -> ObjectIdentifier? {
42-
if let ao = value as? AnyObject {
43-
return ObjectIdentifier(ao)
44-
} else {
45-
return nil
41+
internal static func isClass(_ value: Any) -> Bool {
42+
if let _ = value.dynamicType as? AnyClass {
43+
return true
44+
}
45+
return false
46+
}
47+
48+
internal static func checkValue<T>(
49+
_ value: Any,
50+
ifClass: (AnyObject)->T,
51+
otherwise: ()->T
52+
) -> T {
53+
if isClass(value) {
54+
if let ao = value as? AnyObject {
55+
return ifClass(ao)
56+
}
4657
}
58+
return otherwise()
59+
}
60+
61+
internal static func asObjectIdentifier(_ value: Any) -> ObjectIdentifier? {
62+
return checkValue(value,
63+
ifClass: { return ObjectIdentifier($0) },
64+
otherwise: { return nil })
4765
}
4866

4967
internal static func asNumericValue(_ value: Any) -> Int {
50-
if let ao = value as? AnyObject {
51-
return unsafeBitCast(ao, to: Int.self)
52-
} else {
53-
return 0
54-
}
68+
return checkValue(value,
69+
ifClass: { return unsafeBitCast($0, to: Int.self) },
70+
otherwise: { return 0 })
5571
}
5672

5773
internal static func asStringRepresentation(

test/1_stdlib/DebuggerSupport.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,42 @@ class ClassWithMirror: CustomReflectable {
1919
}
2020
}
2121

22+
#if _runtime(_ObjC)
23+
struct DontBridgeThisStruct {
24+
var message = "Hello World"
25+
}
26+
27+
extension DontBridgeThisStruct : _ObjectiveCBridgeable {
28+
typealias _ObjectiveCType = AnyObject
29+
30+
static func _isBridgedToObjectiveC() -> Bool { return true }
31+
32+
func _bridgeToObjectiveC() -> _ObjectiveCType {
33+
fatalError("tried to bridge DontBridgeThisStruct")
34+
}
35+
36+
static func _forceBridgeFromObjectiveC(
37+
_ source: _ObjectiveCType,
38+
result: inout DontBridgeThisStruct?
39+
) {
40+
result = nil
41+
}
42+
43+
static func _conditionallyBridgeFromObjectiveC(
44+
_ source: _ObjectiveCType,
45+
result: inout DontBridgeThisStruct?
46+
) -> Bool {
47+
result = nil
48+
return false
49+
}
50+
51+
static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?)
52+
-> DontBridgeThisStruct {
53+
return DontBridgeThisStruct()
54+
}
55+
}
56+
#endif
57+
2258
let StringForPrintObjectTests = TestSuite("StringForPrintObject")
2359
StringForPrintObjectTests.test("StructWithMembers") {
2460
let printed = _DebuggerSupport.stringForPrintObject(StructWithMembers())
@@ -57,4 +93,11 @@ StringForPrintObjectTests.test("SomeOptional") {
5793
expectEqual(printed, "▿ Optional<Int>\n - some : 3\n")
5894
}
5995

96+
#if _runtime(_ObjC)
97+
StringForPrintObjectTests.test("DontBridgeThisStruct") {
98+
let printed = _DebuggerSupport.stringForPrintObject(DontBridgeThisStruct())
99+
expectEqual(printed, "▿ DontBridgeThisStruct\n - message : \"Hello World\"\n")
100+
}
101+
#endif
102+
60103
runAllTests()

0 commit comments

Comments
 (0)