Skip to content

Commit fb253b1

Browse files
committed
Use a more efficient SubSequence type for lazy map and filter.
Rather than using the default slice type when slicing the collection produced by a lazy map or filter, slice the base collection and form a new lazy map/filter collection from it. This allows any optimizations provided by the collection SubSequence type to kick in, as well as ensuring that slicing a lazy collection provides the same type as producing a lazy collection of a slice. This is technically source-breaking, because someone could have spelled out the types of slicing a lazy filter or map… but it seems unlikely to matter in practice and the benefits could be significant. Fixes ABI FIXME’s swiftlang#28 and swiftlang#46.
1 parent 31ad22d commit fb253b1

File tree

3 files changed

+15
-40
lines changed

3 files changed

+15
-40
lines changed

stdlib/public/core/Filter.swift.gyb

+5-15
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212

1313
%{
1414
from gyb_stdlib_support import (
15-
collectionForTraversal,
16-
sliceTypeName
15+
collectionForTraversal
1716
)
1817
}%
1918

@@ -115,7 +114,6 @@ public typealias LazyFilterIndex<Base : Collection> = Base.Index
115114

116115
% for Traversal in ['Forward', 'Bidirectional']:
117116
% Self = "LazyFilter" + collectionForTraversal(Traversal)
118-
% Slice = sliceTypeName(traversal=Traversal, mutable=False, rangeReplaceable=False)
119117

120118
/// A lazy `Collection` wrapper that includes the elements of an
121119
/// underlying collection that satisfy a predicate.
@@ -224,9 +222,11 @@ public struct ${Self}<
224222
return _base[position]
225223
}
226224

225+
public typealias SubSequence = ${Self}<Base.SubSequence>
226+
227227
@_inlineable // FIXME(sil-serialize-all)
228-
public subscript(bounds: Range<Index>) -> ${Slice}<${Self}<Base>> {
229-
return ${Slice}(base: self, bounds: bounds)
228+
public subscript(bounds: Range<Index>) -> SubSequence {
229+
return SubSequence(_base: _base[bounds], _predicate)
230230
}
231231

232232
// Any estimate of the number of elements that pass `_predicate` requires
@@ -247,16 +247,6 @@ public struct ${Self}<
247247
return _copySequenceToContiguousArray(self)
248248
}
249249

250-
// FIXME(ABI)#28 (Associated Types with where clauses): we actually want to add:
251-
//
252-
// typealias SubSequence = ${Self}<Base.SubSequence>
253-
//
254-
// so that all slicing optimizations of the base collection can kick in.
255-
//
256-
// We can't do that right now though, because that would force a lot of
257-
// constraints on `Base.SubSequence`, limiting the possible contexts where
258-
// the `.lazy.filter` API can be used.
259-
260250
/// Returns an iterator over the elements of this sequence.
261251
///
262252
/// - Complexity: O(1).

stdlib/public/core/Map.swift.gyb

+5-15
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
%{
1414
from gyb_stdlib_support import (
1515
TRAVERSALS,
16-
collectionForTraversal,
17-
sliceTypeName
16+
collectionForTraversal
1817
)
1918
}%
2019

@@ -104,7 +103,6 @@ public struct LazyMapSequence<Base : Sequence, Element>
104103

105104
% for Traversal in TRAVERSALS:
106105
% Self = "LazyMap" + collectionForTraversal(Traversal)
107-
% Slice = sliceTypeName(traversal=Traversal, mutable=False, rangeReplaceable=False)
108106

109107
/// A `Collection` whose elements consist of those in a `Base`
110108
/// `Collection` passed through a transform function returning `Element`.
@@ -150,21 +148,13 @@ public struct ${Self}<
150148
return _transform(_base[position])
151149
}
152150

151+
public typealias SubSequence = ${Self}<Base.SubSequence, Element>
152+
153153
@_inlineable
154-
public subscript(bounds: Range<Base.Index>) -> ${Slice}<${Self}> {
155-
return ${Slice}(base: self, bounds: bounds)
154+
public subscript(bounds: Range<Base.Index>) -> SubSequence {
155+
return SubSequence(_base: _base[bounds], transform: _transform)
156156
}
157157

158-
// FIXME(ABI)#46 (Associated Types with where clauses): we actually want to add:
159-
//
160-
// typealias SubSequence = ${Self}<Base.SubSequence, Element>
161-
//
162-
// so that all slicing optimizations of the base collection can kick in.
163-
//
164-
// We can't do that right now though, because that would force a lot of
165-
// constraints on `Base.SubSequence`, limiting the possible contexts where
166-
// the `.lazy.map` API can be used.
167-
168158
public typealias IndexDistance = Base.IndexDistance
169159

170160
public typealias Indices = Base.Indices

validation-test/stdlib/Lazy.swift.gyb

+5-10
Original file line numberDiff line numberDiff line change
@@ -874,8 +874,7 @@ tests.test("LazyMapCollection/AssociatedTypes") {
874874
expectCollectionAssociatedTypes(
875875
collectionType: Subject.self,
876876
iteratorType: LazyMapIterator<Base.Iterator, OpaqueValue<Int32>>.self,
877-
// FIXME(ABI)#77 (Associated Types with where clauses): SubSequence should be `LazyMapCollection<Base.Slice>`.
878-
subSequenceType: Slice<Subject>.self,
877+
subSequenceType: LazyMapCollection<Base.SubSequence, OpaqueValue<Int32>>.self,
879878
indexType: Base.Index.self,
880879
indexDistanceType: Base.IndexDistance.self,
881880
indicesType: Base.Indices.self)
@@ -887,8 +886,7 @@ tests.test("LazyMapBidirectionalCollection/AssociatedTypes") {
887886
expectBidirectionalCollectionAssociatedTypes(
888887
collectionType: Subject.self,
889888
iteratorType: LazyMapIterator<Base.Iterator, OpaqueValue<Int32>>.self,
890-
// FIXME(ABI)#78 (Associated Types with where clauses): SubSequence should be `LazyMapBidirectionalCollection<Base.Slice>`.
891-
subSequenceType: BidirectionalSlice<Subject>.self,
889+
subSequenceType: LazyMapBidirectionalCollection<Base.SubSequence, OpaqueValue<Int32>>.self,
892890
indexType: Base.Index.self,
893891
indexDistanceType: Base.IndexDistance.self,
894892
indicesType: Base.Indices.self)
@@ -900,8 +898,7 @@ tests.test("LazyMapRandomAccessCollection/AssociatedTypes") {
900898
expectRandomAccessCollectionAssociatedTypes(
901899
collectionType: Subject.self,
902900
iteratorType: LazyMapIterator<Base.Iterator, OpaqueValue<Int32>>.self,
903-
// FIXME(ABI)#79 (Associated Types with where clauses): SubSequence should be `LazyMapRandomAccessCollection<Base.Slice>`.
904-
subSequenceType: RandomAccessSlice<Subject>.self,
901+
subSequenceType: LazyMapRandomAccessCollection<Base.SubSequence, OpaqueValue<Int32>>.self,
905902
indexType: Base.Index.self,
906903
indexDistanceType: Base.IndexDistance.self,
907904
indicesType: Base.Indices.self)
@@ -1167,8 +1164,7 @@ tests.test("LazyFilterCollection/AssociatedTypes") {
11671164
expectCollectionAssociatedTypes(
11681165
collectionType: Subject.self,
11691166
iteratorType: LazyFilterIterator<Base.Iterator>.self,
1170-
// FIXME(ABI)#80 (Associated Types with where clauses): SubSequence should be `LazyFilterCollection<Base.Slice>`.
1171-
subSequenceType: Slice<Subject>.self,
1167+
subSequenceType: LazyFilterCollection<Base.SubSequence>.self,
11721168
indexType: LazyFilterIndex<Base>.self,
11731169
indexDistanceType: Base.IndexDistance.self,
11741170
indicesType: DefaultIndices<Subject>.self)
@@ -1180,8 +1176,7 @@ tests.test("LazyFilterBidirectionalCollection/AssociatedTypes") {
11801176
expectBidirectionalCollectionAssociatedTypes(
11811177
collectionType: Subject.self,
11821178
iteratorType: LazyFilterIterator<Base.Iterator>.self,
1183-
// FIXME(ABI)#81 (Associated Types with where clauses): SubSequence should be `LazyFilterBidirectionalCollection<Base.Slice>`.
1184-
subSequenceType: BidirectionalSlice<Subject>.self,
1179+
subSequenceType: LazyFilterBidirectionalCollection<Base.SubSequence>.self,
11851180
indexType: LazyFilterIndex<Base>.self,
11861181
indexDistanceType: Base.IndexDistance.self,
11871182
indicesType: DefaultBidirectionalIndices<Subject>.self)

0 commit comments

Comments
 (0)