Skip to content

Commit d9d345f

Browse files
committed
stdlib: Adding missing default implementations of subscript(Range<Index>) for combinations of [Mutable][RangeReplaceable][Bidirectional|RandomAccess]Collection.
These were overlooked, and somehow code that attempted to make a minimal collection conform to RangeReplaceableCollection and RandomAccessCollection managed to compile successfully in Swift 3.0, but in Swift 3.1…*something* changed to reject a type that conforms to both due to the lack of a suitable default slicing subscript implementation in the stdlib that provided all the requirements. Fill in these missing implementations, fixing rdar://problem/30228957.
1 parent 238b91c commit d9d345f

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

stdlib/public/core/MutableCollection.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,30 @@ extension MutableCollection {
372372
}
373373
}
374374

375+
extension MutableCollection where Self: BidirectionalCollection {
376+
public subscript(bounds: Range<Index>) -> MutableBidirectionalSlice<Self> {
377+
get {
378+
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
379+
return MutableBidirectionalSlice(base: self, bounds: bounds)
380+
}
381+
set {
382+
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
383+
}
384+
}
385+
}
386+
387+
extension MutableCollection where Self: RandomAccessCollection {
388+
public subscript(bounds: Range<Index>) -> MutableRandomAccessSlice<Self> {
389+
get {
390+
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
391+
return MutableRandomAccessSlice(base: self, bounds: bounds)
392+
}
393+
set {
394+
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
395+
}
396+
}
397+
}
398+
375399
@available(*, unavailable, renamed: "MutableCollection")
376400
public typealias MutableCollectionType = MutableCollection
377401

stdlib/public/core/RangeReplaceableCollection.swift.gyb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,43 @@ extension RangeReplaceableCollection {
793793
public mutating func reserveCapacity(_ n: IndexDistance) {}
794794
}
795795

796+
// Offer the most specific slice type available for each possible combination of
797+
// RangeReplaceable * (1 + Bidirectional + RandomAccess) * (1 + Mutable)
798+
// collections.
799+
800+
% for capability in ['', 'Bidirectional', 'RandomAccess']:
801+
% if capability:
802+
extension RangeReplaceableCollection where
803+
Self: ${capability}Collection,
804+
Self.SubSequence == RangeReplaceable${capability}Slice<Self> {
805+
public subscript(bounds: Range<Index>)
806+
-> RangeReplaceable${capability}Slice<Self> {
807+
return RangeReplaceable${capability}Slice(base: self, bounds: bounds)
808+
}
809+
}
810+
% end
811+
812+
extension RangeReplaceableCollection where
813+
Self: MutableCollection,
814+
% if capability:
815+
Self: ${capability}Collection,
816+
% end
817+
Self.SubSequence == MutableRangeReplaceable${capability}Slice<Self>
818+
{
819+
public subscript(bounds: Range<Index>)
820+
-> MutableRangeReplaceable${capability}Slice<Self> {
821+
get {
822+
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
823+
return MutableRangeReplaceable${capability}Slice(base: self,
824+
bounds: bounds)
825+
}
826+
set {
827+
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
828+
}
829+
}
830+
}
831+
% end
832+
796833
extension RangeReplaceableCollection where SubSequence == Self {
797834
/// Removes and returns the first element of the collection.
798835
///
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: %gyb %s > %t/collection-combinatorics.swift
4+
// RUN: %target-swift-frontend -typecheck -verify %t/collection-combinatorics.swift
5+
6+
// It should be possible to conform to any combination of
7+
// (1 + RangeReplaceable) * (1 + Bidirectional + RandomAccess) * (1 + Mutable)
8+
// Collection and get reasonable default implementations for slicing
9+
// operations from
10+
// the standard library.
11+
12+
% for mutable in ['', 'Mutable']:
13+
% for rangeReplaceable in ['', 'RangeReplaceable']:
14+
% for capability in ['', 'Bidirectional', 'RandomAccess']:
15+
16+
struct ${mutable}${rangeReplaceable}${capability}Butt
17+
: ${mutable}Collection
18+
% if rangeReplaceable:
19+
, ${rangeReplaceable}Collection
20+
% end
21+
% if capability:
22+
, ${capability}Collection
23+
% end
24+
{
25+
subscript(i: Int) -> Int {
26+
get { return 0 }
27+
% if mutable:
28+
set { }
29+
% end
30+
}
31+
32+
% if capability:
33+
func index(before i: Int) -> Int {
34+
return i - 1
35+
}
36+
% end
37+
func index(after i: Int) -> Int {
38+
return i + 1
39+
}
40+
41+
var startIndex: Int { return .min }
42+
var endIndex: Int { return .max }
43+
44+
% if rangeReplaceable:
45+
init() {}
46+
47+
mutating func replaceSubrange<C: Collection>(_: Range<Int>, with: C)
48+
where C.Iterator.Element == Int
49+
{}
50+
% end
51+
}

0 commit comments

Comments
 (0)