Skip to content

Commit 5c453ce

Browse files
committed
stdlib/Dictionary: add tests for trapping during bridging a Dictionary
whose KeyType is not NSCopyable Swift SVN r18259
1 parent 6808737 commit 5c453ce

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

stdlib/objc/Foundation/Foundation.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,11 @@ func _convertDictionaryToNSDictionary<KeyType, ValueType>(
696696
// Avoid calling the runtime.
697697
bridgedValue = _reinterpretCastToAnyObject(value)
698698
} else {
699-
bridgedValue = bridgeToObjectiveC(value)!
699+
if let theBridgedValue: AnyObject = bridgeToObjectiveC(value) {
700+
bridgedValue = theBridgedValue
701+
} else {
702+
_preconditionFailure("Dictionary to NSDictionary bridging: value failed to bridge")
703+
}
700704
}
701705

702706
// NOTE: the just-bridged key is copied here. It would be nice to avoid
@@ -707,7 +711,12 @@ func _convertDictionaryToNSDictionary<KeyType, ValueType>(
707711
if let nsCopyingKey = bridgedKey as NSCopying {
708712
result[nsCopyingKey] = bridgedValue
709713
} else {
710-
_fatalError("key bridged to an object that does not conform to NSCopying")
714+
// This check is considered not comprehensive because on a different
715+
// code path -- when KeyType bridges verbatim -- we are not doing it
716+
// eagerly. Instead, the message send will fail at runtime when
717+
// NSMutableDictionary attempts to copy the key that does not conform
718+
// to NSCopying.
719+
_debugPreconditionFailure("key bridged to an object that does not conform to NSCopying")
711720
}
712721
}
713722
return reinterpretCast(result)

test/stdlib/DictionaryTraps.swift

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@
1212
// RUN: %target-run %t/a.out RemoveInvalidIndex2 2>&1 | FileCheck %s -check-prefix=CHECK
1313
// RUN: %target-run %t/a.out RemoveInvalidIndex3 2>&1 | FileCheck %s -check-prefix=CHECK
1414
// RUN: %target-run %t/a.out RemoveInvalidIndex4 2>&1 | FileCheck %s -check-prefix=CHECK
15+
// RUN: %target-run %t/a.out BridgedKeyIsNotNSCopyable1 2>&1 | FileCheck %s -check-prefix=CHECK-UNRECOGNIZED-SELECTOR
16+
// RUN: %target-run %t/a.out BridgedKeyIsNotNSCopyable2 2>&1 | FileCheck %s -check-prefix=CHECK
1517

1618
// CHECK: OK
17-
// CHECK: CRASHED: SIG{{ILL|TRAP}}
19+
// CHECK: CRASHED: SIG{{ILL|TRAP|ABRT}}
20+
21+
// CHECK-UNRECOGNIZED-SELECTOR: OK
22+
// CHECK-UNRECOGNIZED-SELECTOR: unrecognized selector sent to instance
23+
// CHECK-UNRECOGNIZED-SELECTOR: CRASHED: SIGABRT
1824

1925
import Foundation
2026

@@ -123,6 +129,42 @@ if arg == "RemoveInvalidIndex4" {
123129
d.removeAtIndex(index)
124130
}
125131

132+
class TestObjCKeyTy : NSObject {
133+
init(_ value: Int) {
134+
self.value = value
135+
}
136+
137+
override func isEqual(object: AnyObject!) -> Bool {
138+
if let other: AnyObject = object {
139+
if let otherObjcKey = other as TestObjCKeyTy {
140+
return self.value == otherObjcKey.value
141+
}
142+
}
143+
return false
144+
}
145+
146+
override var hash : Int {
147+
return value
148+
}
149+
150+
var value: Int
151+
}
152+
153+
if arg == "BridgedKeyIsNotNSCopyable1" {
154+
// This Dictionary is bridged in O(1).
155+
var d = [ TestObjCKeyTy(10): NSObject() ]
156+
var nsd: NSDictionary = d
157+
println("OK")
158+
nsd.mutableCopy()
159+
}
160+
161+
if arg == "BridgedKeyIsNotNSCopyable2" {
162+
// This Dictionary is bridged in O(N).
163+
var d = [ TestObjCKeyTy(10): 10 ]
164+
println("OK")
165+
var nsd: NSDictionary = d
166+
}
167+
126168
println("BUSTED: should have crashed already")
127169
exit(1)
128170

0 commit comments

Comments
 (0)