Skip to content

Commit 57a3df5

Browse files
authored
Merge pull request #29848 from mikeash/eagerly-realize-empty-singletons
[Stdlib] Eagerly realize EmptyDictionarySingleton and EmptySetSingleton.
2 parents 709c58a + 440d279 commit 57a3df5

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

stdlib/public/core/DictionaryStorage.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ internal class __RawDictionaryStorage: __SwiftNativeNSDictionary {
117117
// renamed. The old name must not be used in the new runtime.
118118
@_fixed_layout
119119
@usableFromInline
120+
@_objc_non_lazy_realization
120121
internal class __EmptyDictionarySingleton: __RawDictionaryStorage {
121122
@nonobjc
122123
internal override init(_doNotCallMe: ()) {

stdlib/public/core/SetStorage.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ internal class __RawSetStorage: __SwiftNativeNSSet {
112112
// The old names must not be used in the new runtime.
113113
@_fixed_layout
114114
@usableFromInline
115+
@_objc_non_lazy_realization
115116
internal class __EmptySetSingleton: __RawSetStorage {
116117
@nonobjc
117118
override internal init(_doNotCallMe: ()) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
2+
// Licensed under Apache License v2.0 with Runtime Library Exception
3+
//
4+
// See https://swift.org/LICENSE.txt for license information
5+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// RUN: %target-run-simple-swift | %FileCheck %s
10+
// REQUIRES: executable_test
11+
// REQUIRES: objc_interop
12+
13+
import Foundation
14+
15+
// Test to make sure that empty collections don't cause a crash if we smuggle
16+
// them into the ObjC runtime without doing anything that would trigger
17+
// realization. The ObjC runtime expects all classes to have been realized
18+
// (i.e. runtime data structures initialized, triggered the first time a class
19+
// is accessed or used) before being queried in any way.
20+
//
21+
// Note: this test deliberately avoids StdlibUnittest to make sure
22+
// no other code runs that might inadvertently trigger realization behind our
23+
// back.
24+
25+
@objc protocol P {}
26+
27+
do {
28+
let d: [NSObject: NSObject] = [:]
29+
let c: AnyClass? = object_getClass(d)
30+
let conforms = class_conformsToProtocol(c, P.self)
31+
print("Dictionary: ", conforms) // CHECK: Dictionary: false
32+
}
33+
34+
do {
35+
let a: [NSObject] = []
36+
let c: AnyClass? = object_getClass(a)
37+
let p = objc_getProtocol("NSObject")
38+
let conforms = class_conformsToProtocol(c, p)
39+
print("Array:", conforms) // CHECK: Array: false
40+
}
41+
42+
do {
43+
let s: Set<NSObject> = []
44+
let c: AnyClass? = object_getClass(s)
45+
let p = objc_getProtocol("NSObject")
46+
let conforms = class_conformsToProtocol(c, p)
47+
print("Set:", conforms) // CHECK: Set: false
48+
}

0 commit comments

Comments
 (0)