@@ -73,10 +73,10 @@ extension PathHierarchy.DisambiguationContainer {
73
73
74
74
// Check if any columns are common for all overloads so that type name combinations with those columns can be skipped.
75
75
let allOverloads = IntSet ( 0 ..< listOfOverloadTypeNames. count)
76
- let typeNameIndicesToCheck = ( 0 ..< numberOfTypes) . filter {
76
+ let typeNameIndicesToCheck = IntSet ( ( 0 ..< numberOfTypes) . filter {
77
77
// It's sufficient to check the first row because this column has to be the same for all rows
78
78
table [ 0 ] [ $0] != allOverloads
79
- }
79
+ } )
80
80
81
81
guard !typeNameIndicesToCheck. isEmpty else {
82
82
// Every type name is common across the overloads. This information can't be used to disambiguate the overloads.
@@ -88,15 +88,16 @@ extension PathHierarchy.DisambiguationContainer {
88
88
var shortestDisambiguationSoFar : ( indicesToInclude: IntSet , length: Int ) ?
89
89
90
90
// For each overload we iterate over the possible parameter combinations with increasing number of elements in each combination.
91
- for typeNamesToInclude in typeNameIndicesToCheck. combinations ( ofCount : 1 ... ) {
91
+ for typeNamesToInclude in typeNameIndicesToCheck. combinationsToCheck ( ) {
92
92
// Stop if we've already found a match with fewer parameters than this
93
93
guard typeNamesToInclude. count <= ( shortestDisambiguationSoFar? . indicesToInclude. count ?? . max) else {
94
94
break
95
95
}
96
96
97
- let firstTypeNameToInclude = typeNamesToInclude. first! // The generated `typeNamesToInclude` is never empty.
97
+ var iterator = typeNamesToInclude. makeIterator ( )
98
+ let firstTypeNameToInclude = iterator. next ( ) ! // The generated `typeNamesToInclude` is never empty.
98
99
// Compute which other overloads this combinations of type names also could refer to.
99
- let overlap = typeNamesToInclude . dropFirst ( ) . reduce ( into: table [ row] [ firstTypeNameToInclude] ) { partialResult, index in
100
+ let overlap = IteratorSequence ( iterator ) . reduce ( into: table [ row] [ firstTypeNameToInclude] ) { partialResult, index in
100
101
partialResult. formIntersection ( table [ row] [ index] )
101
102
}
102
103
@@ -133,12 +134,36 @@ extension PathHierarchy.DisambiguationContainer {
133
134
// MARK: Int Set
134
135
135
136
/// A private protocol that abstracts sets of integers.
136
- private protocol _IntSet : SetAlgebra < Int > {
137
+ private protocol _IntSet : SetAlgebra < Int > , Sequence < Int > {
137
138
// In addition to the general SetAlgebra, the code in this file checks the number of elements in the set.
138
139
var count : Int { get }
140
+
141
+ // Let each type specialize the creation of possible combinations to check.
142
+ associatedtype CombinationSequence : Sequence < Self >
143
+ func combinationsToCheck( ) -> CombinationSequence
144
+ }
145
+
146
+
147
+ extension Set < Int > : _IntSet {
148
+ func combinationsToCheck( ) -> some Sequence < Self > {
149
+ // For `Set<Int>`, use the Swift Algorithms implementation to generate the possible combinations.
150
+ self . combinations ( ofCount: 1 ... ) . lazy. map { Set ( $0) }
151
+ }
152
+ }
153
+ extension _TinySmallValueIntSet : _IntSet {
154
+ func combinationsToCheck( ) -> [ Self ] {
155
+ // For `_TinySmallValueIntSet`, leverage the fact that bits of an Int represent the possible combinations.
156
+ let smallest = storage. trailingZeroBitCount
157
+ return ( 1 ... storage >> smallest)
158
+ . compactMap {
159
+ let combination = Self ( storage: UInt64 ( $0 << smallest) )
160
+ // Filter out any combinations that include columns that are the same for all overloads
161
+ return self . isSuperset ( of: combination) ? combination : nil
162
+ }
163
+ // The bits of larger and larger Int values won't be in order of number of bits set, so we sort them.
164
+ . sorted ( by: { $0. count < $1. count } )
165
+ }
139
166
}
140
- extension Set < Int > : _IntSet { }
141
- extension _TinySmallValueIntSet : _IntSet { }
142
167
143
168
/// A specialized set-algebra type that only stores the possible values `0 ..< 64`.
144
169
///
@@ -233,3 +258,38 @@ struct _TinySmallValueIntSet: SetAlgebra {
233
258
storage ^= other. storage
234
259
}
235
260
}
261
+
262
+ extension _TinySmallValueIntSet : Sequence {
263
+ func makeIterator( ) -> Iterator {
264
+ Iterator ( set: self )
265
+ }
266
+
267
+ struct Iterator : IteratorProtocol {
268
+ typealias Element = Int
269
+
270
+ private let set : _TinySmallValueIntSet
271
+ private var current : Int
272
+ private let end : Int
273
+
274
+ @inlinable
275
+ init ( set: _TinySmallValueIntSet ) {
276
+ self . set = set
277
+ self . current = set. storage. trailingZeroBitCount
278
+ self . end = 64 - set. storage. leadingZeroBitCount
279
+ }
280
+
281
+ @inlinable
282
+ mutating func next( ) -> Int ? {
283
+ defer { current += 1 }
284
+
285
+ while !set. contains ( current) {
286
+ current += 1
287
+ if end <= current {
288
+ return nil
289
+ }
290
+ }
291
+
292
+ return current
293
+ }
294
+ }
295
+ }
0 commit comments