Skip to content

Commit 10ea278

Browse files
authored
Merge pull request #70762 from kubamracek/embedded-dict
[embedded] Add Dictionary to embedded stdlib
2 parents 05dbd05 + cf2437a commit 10ea278

10 files changed

+126
-34
lines changed

stdlib/public/core/CMakeLists.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ split_embedded_sources(
6565
NORMAL CString.swift
6666
EMBEDDED CTypes.swift
6767
NORMAL DebuggerSupport.swift
68-
NORMAL Dictionary.swift
69-
NORMAL DictionaryBridging.swift
70-
NORMAL DictionaryBuilder.swift
71-
NORMAL DictionaryCasting.swift
72-
NORMAL DictionaryStorage.swift
73-
NORMAL DictionaryVariant.swift
68+
EMBEDDED Dictionary.swift
69+
EMBEDDED DictionaryBridging.swift
70+
EMBEDDED DictionaryBuilder.swift
71+
EMBEDDED DictionaryCasting.swift
72+
EMBEDDED DictionaryStorage.swift
73+
EMBEDDED DictionaryVariant.swift
7474
NORMAL DiscontiguousSlice.swift
7575
NORMAL DropWhile.swift
7676
NORMAL Dump.swift
@@ -99,8 +99,8 @@ split_embedded_sources(
9999
NORMAL Join.swift
100100
NORMAL KeyPath.swift
101101
NORMAL KeyValuePairs.swift
102-
NORMAL LazyCollection.swift
103-
NORMAL LazySequence.swift
102+
EMBEDDED LazyCollection.swift
103+
EMBEDDED LazySequence.swift
104104
NORMAL LegacyABI.swift
105105
EMBEDDED LifetimeManager.swift
106106
NORMAL Macros.swift
@@ -111,7 +111,7 @@ split_embedded_sources(
111111
NORMAL Mirrors.swift
112112
EMBEDDED Misc.swift
113113
EMBEDDED MutableCollection.swift
114-
NORMAL NativeDictionary.swift
114+
EMBEDDED NativeDictionary.swift
115115
EMBEDDED NativeSet.swift
116116
NORMAL NewtypeWrapper.swift
117117
NORMAL NFC.swift

stdlib/public/core/Dictionary.swift

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,9 +1284,7 @@ extension Dictionary {
12841284

12851285
/// A view of a dictionary's keys.
12861286
@frozen
1287-
public struct Keys
1288-
: Collection, Equatable,
1289-
CustomStringConvertible, CustomDebugStringConvertible {
1287+
public struct Keys: Collection, Equatable {
12901288
public typealias Element = Key
12911289
public typealias SubSequence = Slice<Dictionary.Keys>
12921290

@@ -1399,20 +1397,11 @@ extension Dictionary {
13991397

14001398
return true
14011399
}
1402-
1403-
public var description: String {
1404-
return _makeCollectionDescription()
1405-
}
1406-
1407-
public var debugDescription: String {
1408-
return _makeCollectionDescription(withTypeName: "Dictionary.Keys")
1409-
}
14101400
}
14111401

14121402
/// A view of a dictionary's values.
14131403
@frozen
1414-
public struct Values
1415-
: MutableCollection, CustomStringConvertible, CustomDebugStringConvertible {
1404+
public struct Values: MutableCollection {
14161405
public typealias Element = Value
14171406

14181407
@usableFromInline
@@ -1482,14 +1471,6 @@ extension Dictionary {
14821471
return count == 0
14831472
}
14841473

1485-
public var description: String {
1486-
return _makeCollectionDescription()
1487-
}
1488-
1489-
public var debugDescription: String {
1490-
return _makeCollectionDescription(withTypeName: "Dictionary.Values")
1491-
}
1492-
14931474
@inlinable
14941475
public mutating func swapAt(_ i: Index, _ j: Index) {
14951476
guard i != j else { return }
@@ -1507,6 +1488,30 @@ extension Dictionary {
15071488
}
15081489
}
15091490

1491+
@_unavailableInEmbedded
1492+
extension Dictionary.Keys
1493+
: CustomStringConvertible, CustomDebugStringConvertible {
1494+
public var description: String {
1495+
return _makeCollectionDescription()
1496+
}
1497+
1498+
public var debugDescription: String {
1499+
return _makeCollectionDescription(withTypeName: "Dictionary.Keys")
1500+
}
1501+
}
1502+
1503+
@_unavailableInEmbedded
1504+
extension Dictionary.Values
1505+
: CustomStringConvertible, CustomDebugStringConvertible {
1506+
public var description: String {
1507+
return _makeCollectionDescription()
1508+
}
1509+
1510+
public var debugDescription: String {
1511+
return _makeCollectionDescription(withTypeName: "Dictionary.Values")
1512+
}
1513+
}
1514+
15101515
extension Dictionary.Keys {
15111516
@frozen
15121517
public struct Iterator: IteratorProtocol {
@@ -1614,13 +1619,15 @@ extension Dictionary: Hashable where Value: Hashable {
16141619
}
16151620
}
16161621

1622+
@_unavailableInEmbedded
16171623
extension Dictionary: _HasCustomAnyHashableRepresentation
16181624
where Value: Hashable {
16191625
public __consuming func _toCustomAnyHashable() -> AnyHashable? {
16201626
return AnyHashable(_box: _DictionaryAnyHashableBox(self))
16211627
}
16221628
}
16231629

1630+
@_unavailableInEmbedded
16241631
internal struct _DictionaryAnyHashableBox<Key: Hashable, Value: Hashable>
16251632
: _AnyHashableBox {
16261633
internal let _value: Dictionary<Key, Value>
@@ -1673,6 +1680,7 @@ internal struct _DictionaryAnyHashableBox<Key: Hashable, Value: Hashable>
16731680
}
16741681
}
16751682

1683+
@_unavailableInEmbedded
16761684
extension Collection {
16771685
// Utility method for KV collections that wish to implement
16781686
// CustomStringConvertible and CustomDebugStringConvertible using a bracketed
@@ -1706,6 +1714,7 @@ extension Collection {
17061714
}
17071715
}
17081716

1717+
@_unavailableInEmbedded
17091718
extension Dictionary: CustomStringConvertible, CustomDebugStringConvertible {
17101719
/// A string that represents the contents of the dictionary.
17111720
public var description: String {

stdlib/public/core/DictionaryCasting.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ extension Dictionary {
4242
/// protocols (such as `AnyObject`) of `DerivedKey` and `DerivedValue`,
4343
/// respectively.
4444
@inlinable
45+
@_unavailableInEmbedded
4546
public func _dictionaryUpCast<DerivedKey, DerivedValue, BaseKey, BaseValue>(
4647
_ source: Dictionary<DerivedKey, DerivedValue>
4748
) -> Dictionary<BaseKey, BaseValue> {
@@ -58,6 +59,7 @@ public func _dictionaryUpCast<DerivedKey, DerivedValue, BaseKey, BaseValue>(
5859

5960
/// Called by the casting machinery.
6061
@_silgen_name("_swift_dictionaryDownCastIndirect")
62+
@_unavailableInEmbedded
6163
internal func _dictionaryDownCastIndirect<SourceKey, SourceValue,
6264
TargetKey, TargetValue>(
6365
_ source: UnsafePointer<Dictionary<SourceKey, SourceValue>>,
@@ -73,6 +75,7 @@ internal func _dictionaryDownCastIndirect<SourceKey, SourceValue,
7375
/// - Precondition: `DerivedKey` is a subtype of `BaseKey`, `DerivedValue` is
7476
/// a subtype of `BaseValue`, and all of these types are reference types.
7577
@inlinable
78+
@_unavailableInEmbedded
7679
public func _dictionaryDownCast<BaseKey, BaseValue, DerivedKey, DerivedValue>(
7780
_ source: Dictionary<BaseKey, BaseValue>
7881
) -> Dictionary<DerivedKey, DerivedValue> {
@@ -111,6 +114,7 @@ public func _dictionaryDownCast<BaseKey, BaseValue, DerivedKey, DerivedValue>(
111114

112115
/// Called by the casting machinery.
113116
@_silgen_name("_swift_dictionaryDownCastConditionalIndirect")
117+
@_unavailableInEmbedded
114118
internal func _dictionaryDownCastConditionalIndirect<SourceKey, SourceValue,
115119
TargetKey, TargetValue>(
116120
_ source: UnsafePointer<Dictionary<SourceKey, SourceValue>>,
@@ -132,6 +136,7 @@ internal func _dictionaryDownCastConditionalIndirect<SourceKey, SourceValue,
132136
/// - Precondition: `DerivedKey` is a subtype of `BaseKey`, `DerivedValue` is
133137
/// a subtype of `BaseValue`, and all of these types are reference types.
134138
@inlinable
139+
@_unavailableInEmbedded
135140
public func _dictionaryDownCastConditional<
136141
BaseKey, BaseValue, DerivedKey, DerivedValue
137142
>(

stdlib/public/core/DictionaryStorage.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,29 @@ extension __EmptyDictionarySingleton: _NSDictionaryCore {
187187
}
188188
#endif
189189

190+
#if $Embedded
191+
// In embedded Swift, the stdlib is a .swiftmodule only without any .o/.a files,
192+
// to allow consuming it by clients with different LLVM codegen setting (-mcpu
193+
// flags, etc.), which means we cannot declare the singleton in a C/C++ file.
194+
//
195+
// TODO: We should figure out how to make this a constant so that it's placed in
196+
// non-writable memory (can't be a let, Builtin.addressof below requires a var).
197+
public var _swiftEmptyDictionarySingleton: (Int, Int, Int, Int, UInt8, UInt8, UInt16, UInt32, Int, Int, Int, Int) =
198+
(
199+
/*isa*/0, /*refcount*/-1, // HeapObject header
200+
/*count*/0,
201+
/*capacity*/0,
202+
/*scale*/0,
203+
/*reservedScale*/0,
204+
/*extra*/0,
205+
/*age*/0,
206+
/*seed*/0,
207+
/*rawKeys*/1,
208+
/*rawValues*/1,
209+
/*metadata*/~1
210+
)
211+
#endif
212+
190213
extension __RawDictionaryStorage {
191214
/// The empty singleton that is used for every single Dictionary that is
192215
/// created without any elements. The contents of the storage should never

stdlib/public/core/DictionaryVariant.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ extension Dictionary {
4646
@inlinable
4747
@inline(__always)
4848
init(dummy: Void) {
49-
#if _pointerBitWidth(_64)
49+
#if _pointerBitWidth(_64) && !$Embedded
5050
self.object = _BridgeStorage(taggedPayload: 0)
51-
#elseif _pointerBitWidth(_32)
51+
#elseif _pointerBitWidth(_32) || $Embedded
5252
self.init(native: _NativeDictionary())
5353
#else
5454
#error("Unknown platform")

stdlib/public/core/NativeDictionary.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ extension _NativeDictionary {
444444
// This function has a highly visible name to make it stand out in stack traces.
445445
@usableFromInline
446446
@inline(never)
447+
@_unavailableInEmbedded
447448
internal func KEY_TYPE_OF_DICTIONARY_VIOLATES_HASHABLE_REQUIREMENTS(
448449
_ keyType: Any.Type
449450
) -> Never {
@@ -472,7 +473,11 @@ extension _NativeDictionary { // Insertions
472473
// because we'll need to compare elements in case of hash collisions.
473474
let (bucket, found) = find(key, hashValue: hashValue)
474475
guard !found else {
476+
#if !$Embedded
475477
KEY_TYPE_OF_DICTIONARY_VIOLATES_HASHABLE_REQUIREMENTS(Key.self)
478+
#else
479+
fatalError("duplicate keys in a Dictionary")
480+
#endif
476481
}
477482
hashTable.insert(bucket)
478483
uncheckedInitialize(at: bucket, toKey: key, value: value)
@@ -537,7 +542,11 @@ extension _NativeDictionary { // Insertions
537542
guard rehashed else { return (bucket, found) }
538543
let (b, f) = find(key)
539544
if f != found {
545+
#if !$Embedded
540546
KEY_TYPE_OF_DICTIONARY_VIOLATES_HASHABLE_REQUIREMENTS(Key.self)
547+
#else
548+
fatalError("duplicate keys in a Dictionary")
549+
#endif
541550
}
542551
return (b, found)
543552
}
@@ -767,7 +776,11 @@ extension _NativeDictionary { // High-level operations
767776
let newValue = try combine(uncheckedValue(at: bucket), value)
768777
_values[bucket.offset] = newValue
769778
} catch _MergeError.keyCollision {
779+
#if !$Embedded
770780
fatalError("Duplicate values for key: '\(key)'")
781+
#else
782+
fatalError("Duplicate values for a key in a Dictionary")
783+
#endif
771784
}
772785
} else {
773786
_insert(at: bucket, key: key, value: value)

stdlib/public/core/SetStorage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public var _swiftEmptySetSingleton: (Int, Int, Int, Int, UInt8, UInt8, UInt16, U
145145
/*age*/0,
146146
/*seed*/0,
147147
/*rawElements*/1,
148-
/*metadata*/-1
148+
/*metadata*/~1
149149
)
150150
#endif
151151

test/IDE/complete_embedded.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ func test() {
1111
// GLOBAL: Literal[Nil]/None: nil;
1212
// GLOBAL: Literal[String]/None: "{#(abc)#}"[#String#];
1313
// GLOBAL: Literal[Array]/None: [{#(values)#}][#Array#];
14-
// GLOBAL: Literal[Dictionary]/None: [{#(key)#}: {#(value)#}];
14+
// GLOBAL: Literal[Dictionary]/None: [{#(key)#}: {#(value)#}][#Dictionary#];
1515
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-run-simple-swift(-parse-as-library -enable-experimental-feature Embedded -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop -Xlinker -dead_strip) | %FileCheck %s
2+
// RUN: %target-run-simple-swift(-parse-as-library -O -enable-experimental-feature Embedded -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop -Xlinker -dead_strip) | %FileCheck %s
3+
// RUN: %target-run-simple-swift(-parse-as-library -Osize -enable-experimental-feature Embedded -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop -Xlinker -dead_strip) | %FileCheck %s
4+
5+
// REQUIRES: swift_in_compiler
6+
// REQUIRES: executable_test
7+
// REQUIRES: optimized_stdlib
8+
// REQUIRES: OS=macosx
9+
10+
@main
11+
struct Main {
12+
static func main() {
13+
var dict: [Int: StaticString] = [:]
14+
dict[11] = "hello"
15+
dict[33] = "!"
16+
dict[22] = "world"
17+
for key in dict.keys.sorted() {
18+
print(dict[key]!, terminator: " ")
19+
}
20+
print("")
21+
}
22+
}
23+
24+
// CHECK: hello world !

test/embedded/stdlib-dictionary.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend -target armv7-apple-none-macho -Xcc -D__MACH__ -emit-ir %s -enable-experimental-feature Embedded | %FileCheck %s
2+
// RUN: %target-swift-frontend -target arm64-apple-none-macho -Xcc -D__MACH__ -Xcc -D__arm64__ -Xcc -D__APPLE__ -emit-ir %s -enable-experimental-feature Embedded | %FileCheck %s
3+
4+
// REQUIRES: swift_in_compiler
5+
// REQUIRES: optimized_stdlib
6+
7+
public func test() {
8+
var d: [Int:Int] = [1: 2, 3: 4, 5: 6]
9+
d[8] = 9
10+
d.keys.sorted()
11+
d.values.allSatisfy { $0 > 0 }
12+
d.keys.contains { $0 > 0 }
13+
d.values.map { $0 * 2 }
14+
}
15+
16+
test()
17+
18+
// CHECK: define {{.*}}i32 @main(i32 %0, ptr %1)

0 commit comments

Comments
 (0)