Skip to content

Commit c65e3ca

Browse files
authored
Merge pull request #9750 from moiseev/rrc-filter-4
[swift-4.0-branch][stdlib] Add a Swift 4 only RangeRepleaceable.filter returning Self
2 parents 704deff + e12954e commit c65e3ca

File tree

5 files changed

+93
-0
lines changed

5 files changed

+93
-0
lines changed

stdlib/public/core/Arrays.swift.gyb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,16 @@ extension ${Self} : RangeReplaceableCollection, _ArrayProtocol {
15741574
}
15751575
}
15761576

1577+
// Since RangeReplaceableCollection now has a version of filter that is less
1578+
// efficient, we should make the default implementation coming from Sequence
1579+
// preferred.
1580+
@_inlineable
1581+
public func filter(
1582+
_ isIncluded: (Element) throws -> Bool
1583+
) rethrows -> [Element] {
1584+
return try _filter(isIncluded)
1585+
}
1586+
15771587
//===--- algorithms -----------------------------------------------------===//
15781588

15791589
@_inlineable

stdlib/public/core/RangeReplaceableCollection.swift.gyb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,31 @@ public func += <
12121212
lhs.append(contentsOf: rhs)
12131213
}
12141214

1215+
extension RangeReplaceableCollection {
1216+
/// Returns a new collection of the same type containing, in order, the
1217+
/// elements of the original collection that satisfy the given predicate.
1218+
///
1219+
/// In this example, `filter(_:)` is used to include only names shorter than
1220+
/// five characters.
1221+
///
1222+
/// let cast = ["Vivien", "Marlon", "Kim", "Karl"]
1223+
/// let shortNames = cast.filter { $0.count < 5 }
1224+
/// print(shortNames)
1225+
/// // Prints "["Kim", "Karl"]"
1226+
///
1227+
/// - Parameter isIncluded: A closure that takes an element of the
1228+
/// sequence as its argument and returns a Boolean value indicating
1229+
/// whether the element should be included in the returned array.
1230+
/// - Returns: An array of the elements that `isIncluded` allowed.
1231+
@_inlineable
1232+
@available(swift, introduced: 4.0)
1233+
public func filter(
1234+
_ isIncluded: (Element) throws -> Bool
1235+
) rethrows -> Self {
1236+
return try Self(self.lazy.filter(isIncluded))
1237+
}
1238+
}
1239+
12151240
@available(*, unavailable, renamed: "RangeReplaceableCollection")
12161241
public typealias RangeReplaceableCollectionType = RangeReplaceableCollection
12171242

stdlib/public/core/Sequence.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,13 @@ extension Sequence {
877877
public func filter(
878878
_ isIncluded: (Element) throws -> Bool
879879
) rethrows -> [Element] {
880+
return try _filter(isIncluded)
881+
}
882+
883+
@_transparent
884+
public func _filter(
885+
_ isIncluded: (Element) throws -> Bool
886+
) rethrows -> [Element] {
880887

881888
var result = ContiguousArray<Element>()
882889

test/stdlib/ArrayFilter.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-swift-frontend -swift-version 4 -O %s -emit-sil | %FileCheck %s
2+
3+
// This test is testing that even in presence of
4+
// RangeReplaceableCollection.filter(_:), Arrays are still calling the default
5+
// implementation from Sequence.
6+
7+
// CHECK-NOT: RangeReplaceableCollection.filter(_:)
8+
@inline(never)
9+
public func foobar(_ xs: [Int]) -> [Int] {
10+
return xs.filter { _ in false }
11+
}
12+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: rm -rf %t ; mkdir -p %t
2+
// RUN: %target-build-swift %s -o %t/a.out3 -swift-version 3 && %target-run %t/a.out3
3+
// RUN: %target-build-swift %s -o %t/a.out4 -swift-version 4 && %target-run %t/a.out4
4+
5+
import StdlibUnittest
6+
7+
var tests = TestSuite("RangeReplaceableFilterCompatibility")
8+
9+
tests.test("String.filter return type") {
10+
var filtered = "Hello, World".filter { $0 < "A" }
11+
#if swift(>=4)
12+
expectType(String.self, &filtered)
13+
#else
14+
expectType([Character].self, &filtered)
15+
#endif
16+
}
17+
18+
tests.test("Array.filter return type") {
19+
var filtered = Array(0..<10).filter { $0 % 2 == 0 }
20+
expectType([Int].self, &filtered)
21+
}
22+
23+
tests.test("ContiguousArray.filter return type") {
24+
var filtered = ContiguousArray(0..<10).filter { $0 % 2 == 0 }
25+
expectType([Int].self, &filtered)
26+
}
27+
28+
tests.test("ArraySlice.filter return type") {
29+
var filtered = Array(0..<10)[0..<10].filter { $0 % 2 == 0 }
30+
expectType([Int].self, &filtered)
31+
}
32+
33+
tests.test("String.filter can return [Character]") {
34+
let filtered = "Hello, World".filter { "A" <= $0 && $0 <= "Z"} as [Character]
35+
expectEqualSequence("HW", filtered)
36+
}
37+
38+
runAllTests()
39+

0 commit comments

Comments
 (0)