Skip to content

[4.0] Add recursive where clauses to Collection protocols #9404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,7 @@ public func checkCollection<${genericParam}, C : Collection>(
${TRACE},
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
sameValue: (${Element}, ${Element}) -> Bool
) where C.Iterator.Element == ${Element},
C.SubSequence : Collection {
) where C.Iterator.Element == ${Element} {

checkForwardCollection(expected, collection, message(),
stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
Expand All @@ -278,7 +277,6 @@ public func check${Traversal}Collection<
resiliencyChecks: CollectionMisuseResiliencyChecks = .all
) where
C.Iterator.Element == ${Element},
C.SubSequence : ${TraversalCollection},
${Element} : Equatable {

check${Traversal}Collection(
Expand All @@ -298,8 +296,7 @@ public func check${Traversal}Collection<
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
sameValue: (${Element}, ${Element}) -> Bool
) where
C.Iterator.Element == ${Element},
C.SubSequence : ${TraversalCollection} {
C.Iterator.Element == ${Element} {

checkOneLevelOf${Traversal}Collection(expected, collection, ${trace},
resiliencyChecks: resiliencyChecks, sameValue: sameValue)
Expand Down Expand Up @@ -504,8 +501,7 @@ ${genericParam}, S : ${TraversalCollection}
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
sameValue: (${Element}, ${Element}) -> Bool
) where
S.Iterator.Element == ${Element},
S.SubSequence : ${TraversalCollection} {
S.Iterator.Element == ${Element} {

let expectedArray = Array(expected)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -471,16 +471,9 @@ internal enum _SubSequenceSubscriptOnRangeMode {
%{
from gyb_stdlib_support import collectionForTraversal
def testConstraints(protocol):
if protocol == 'Collection':
subseq_as_collection = 'CollectionWithEquatableElement.SubSequence : Collection,'
else:
subseq_as_collection=''
return '''
C : %(protocol)s,
CollectionWithEquatableElement : %(protocol)s,
%(subseq_as_collection)s
C.SubSequence : %(protocol)s,
C.Indices : %(protocol)s,
CollectionWithEquatableElement.Iterator.Element : Equatable
''' % locals()

Expand All @@ -494,6 +487,7 @@ internal enum _SubSequenceSubscriptOnRangeMode {
[CollectionWithEquatableElement.Iterator.Element]
) -> CollectionWithEquatableElement,


wrapValueIntoEquatable: @escaping (
MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ extension TestSuite {
isFixedLengthCollection: Bool,
collectionIsBidirectional: Bool = false
) where
C.SubSequence : MutableCollection,
C.Indices : Collection,
CollectionWithEquatableElement.Iterator.Element : Equatable,
CollectionWithComparableElement.Iterator.Element : Comparable {

Expand Down Expand Up @@ -783,8 +781,6 @@ self.test("\(testNamePrefix).partition/InvalidOrderings") {
withUnsafeMutableBufferPointerIsSupported: Bool,
isFixedLengthCollection: Bool
) where
C.SubSequence : BidirectionalCollection & MutableCollection,
C.Indices : BidirectionalCollection,
CollectionWithEquatableElement.Iterator.Element : Equatable,
CollectionWithComparableElement.Iterator.Element : Comparable {

Expand Down Expand Up @@ -929,8 +925,6 @@ self.test("\(testNamePrefix).partition/DispatchesThrough_withUnsafeMutableBuffer
withUnsafeMutableBufferPointerIsSupported: Bool,
isFixedLengthCollection: Bool
) where
C.SubSequence : RandomAccessCollection & MutableCollection,
C.Indices : RandomAccessCollection,
CollectionWithEquatableElement.Iterator.Element : Equatable,
CollectionWithComparableElement.Iterator.Element : Comparable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,10 +462,7 @@ extension TestSuite {
outOfBoundsIndexOffset: Int = 1,
collectionIsBidirectional: Bool = false
) where
C.SubSequence : Collection,
C.Indices : Collection,
CollectionWithEquatableElement.Iterator.Element : Equatable,
CollectionWithEquatableElement.SubSequence : Collection {
CollectionWithEquatableElement.Iterator.Element : Equatable {

var testNamePrefix = testNamePrefix

Expand Down Expand Up @@ -1180,8 +1177,6 @@ self.test("\(testNamePrefix).OperatorPlus") {
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
outOfBoundsIndexOffset: Int = 1
) where
C.SubSequence : BidirectionalCollection & RangeReplaceableCollection,
C.Indices : BidirectionalCollection,
CollectionWithEquatableElement.Iterator.Element : Equatable {

var testNamePrefix = testNamePrefix
Expand Down Expand Up @@ -1302,8 +1297,6 @@ self.test("\(testNamePrefix).removeLast(n: Int)/whereIndexIsBidirectional/remove
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
outOfBoundsIndexOffset: Int = 1
) where
C.SubSequence : RandomAccessCollection & RangeReplaceableCollection,
C.Indices : RandomAccessCollection,
CollectionWithEquatableElement.Iterator.Element : Equatable {

var testNamePrefix = testNamePrefix
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ extension TestSuite {
collectionIsBidirectional: Bool = false
) where
C.SubSequence == C,
C.Indices : Collection,
CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement,
CollectionWithEquatableElement.Iterator.Element : Equatable {

Expand Down Expand Up @@ -165,7 +164,6 @@ extension TestSuite {
outOfBoundsIndexOffset: Int = 1
) where
C.SubSequence == C,
C.Indices : BidirectionalCollection,
CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement,
CollectionWithEquatableElement.Iterator.Element : Equatable {

Expand Down Expand Up @@ -310,7 +308,6 @@ extension TestSuite {
outOfBoundsIndexOffset: Int = 1
) where
C.SubSequence == C,
C.Indices : RandomAccessCollection,
CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement,
CollectionWithEquatableElement.Iterator.Element : Equatable {

Expand Down
30 changes: 4 additions & 26 deletions stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -376,14 +376,7 @@ public func expectSequenceType<X : Sequence>(_ x: X) -> X
% for Mutable in ['', 'Mutable']:
public func expect${Mutable}CollectionType<X : ${Mutable}Collection>(
_ x: X.Type
) where
// FIXME(ABI)#2 (Associated Types with where clauses): there should be no constraints in
// the 'where' clause, all of these should be required by the protocol.
% if Mutable == '':
X.SubSequence : Collection,
% end
// X.SubSequence.Indices == X.Indices, // FIXME(ABI)#3 (Recursive Protocol Constraints): can't have this constraint now.
X.Indices : Collection {}
) { }
% end

/// A slice is a `Collection` that when sliced returns an instance of
Expand Down Expand Up @@ -421,12 +414,7 @@ public func expectCollectionAssociatedTypes<X : Collection>(
indexType: X.Index.Type,
indexDistanceType: X.IndexDistance.Type,
indicesType: X.Indices.Type
) where
// FIXME(ABI)#6 (Associated Types with where clauses): there should be no constraints in
// the 'where' clause, all of these should be required by the protocol.
X.SubSequence : Collection,
// X.SubSequence.Indices == X.Indices, // FIXME(ABI)#7 (Recursive Protocol Constraints): can't have this constraint now.
X.Indices : Collection {}
) { }

/// Check that all associated types of a `BidirectionalCollection` are what we
/// expect them to be.
Expand All @@ -437,12 +425,7 @@ public func expectBidirectionalCollectionAssociatedTypes<X : BidirectionalCollec
indexType: X.Index.Type,
indexDistanceType: X.IndexDistance.Type,
indicesType: X.Indices.Type
) where
// FIXME(ABI)#8 (Associated Types with where clauses): there should be no constraints in
// the 'where' clause, all of these should be required by the protocol.
X.SubSequence : BidirectionalCollection,
// X.SubSequence.Indices == X.Indices, // FIXME(ABI)#9 (Recursive Protocol Constraints): can't have this constraint now.
X.Indices : BidirectionalCollection {}
) { }

/// Check that all associated types of a `RandomAccessCollection` are what we
/// expect them to be.
Expand All @@ -453,12 +436,7 @@ public func expectRandomAccessCollectionAssociatedTypes<X : RandomAccessCollecti
indexType: X.Index.Type,
indexDistanceType: X.IndexDistance.Type,
indicesType: X.Indices.Type
) where
// FIXME(ABI)#10 (Associated Types with where clauses): there should be no constraints in
// the 'where' clause, all of these should be required by the protocol.
X.SubSequence : RandomAccessCollection,
// X.SubSequence.Indices == X.Indices, // FIXME(ABI)#11 (Recursive Protocol Constraints): can't have this constraint now.
X.Indices : RandomAccessCollection {}
) { }

public struct AssertionResult : CustomStringConvertible {
init(isPass: Bool) {
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/ArrayBufferProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
internal protocol _ArrayBufferProtocol
: MutableCollection, RandomAccessCollection {

associatedtype Indices : RandomAccessCollection = CountableRange<Int>
associatedtype Indices = CountableRange<Int>

/// The type of elements stored in the buffer.
associatedtype Element
Expand Down
14 changes: 4 additions & 10 deletions stdlib/public/core/BidirectionalCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ public protocol _BidirectionalIndexable : _Indexable {
/// `c.index(before: c.index(after: i)) == i`.
/// - If `i > c.startIndex && i <= c.endIndex`
/// `c.index(after: c.index(before: i)) == i`.
public protocol BidirectionalCollection
: _BidirectionalIndexable, Collection {
public protocol BidirectionalCollection : _BidirectionalIndexable, Collection
where SubSequence: BidirectionalCollection, Indices: BidirectionalCollection {

// TODO: swift-3-indexing-model - replaces functionality in BidirectionalIndex
/// Returns the position immediately before the given index.
Expand All @@ -84,17 +84,11 @@ public protocol BidirectionalCollection

/// A sequence that can represent a contiguous subrange of the collection's
/// elements.
associatedtype SubSequence : _BidirectionalIndexable, Collection
= BidirectionalSlice<Self>
// FIXME(ABI)#93 (Recursive Protocol Constraints):
// associatedtype SubSequence : BidirectionalCollection
associatedtype SubSequence = BidirectionalSlice<Self>

/// A type that represents the indices that are valid for subscripting the
/// collection, in ascending order.
associatedtype Indices : _BidirectionalIndexable, Collection
= DefaultBidirectionalIndices<Self>
// FIXME(ABI)#95 (Recursive Protocol Constraints):
// associatedtype Indices : BidirectionalCollection
associatedtype Indices = DefaultBidirectionalIndices<Self>

/// The indices that are valid for subscripting the collection, in ascending
/// order.
Expand Down
16 changes: 9 additions & 7 deletions stdlib/public/core/Collection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,10 @@ public struct IndexingIterator<
/// forward or bidirectional collection must traverse the entire collection to
/// count the number of contained elements, accessing its `count` property is
/// an O(*n*) operation.
public protocol Collection : _Indexable, Sequence {
public protocol Collection : _Indexable, Sequence
where SubSequence: Collection, Indices: Collection,
SubSequence.Index == Index
{
/// A type that represents the number of steps between a pair of
/// indices.
associatedtype IndexDistance = Int
Expand All @@ -668,10 +671,10 @@ public protocol Collection : _Indexable, Sequence {
/// This associated type appears as a requirement in the `Sequence`
/// protocol, but it is restated here with stricter constraints. In a
/// collection, the subsequence should also conform to `Collection`.
associatedtype SubSequence : _IndexableBase, Sequence = Slice<Self>
where Self.SubSequence.Index == Index,
Self.Iterator.Element == Self.SubSequence.Iterator.Element,
associatedtype SubSequence = Slice<Self>
where Iterator.Element == SubSequence.Iterator.Element,
SubSequence.SubSequence == SubSequence

// FIXME(ABI)#98 (Recursive Protocol Constraints):
// FIXME(ABI)#99 (Associated Types with where clauses):
// associatedtype SubSequence : Collection
Expand Down Expand Up @@ -732,10 +735,9 @@ public protocol Collection : _Indexable, Sequence {

/// A type that represents the indices that are valid for subscripting the
/// collection, in ascending order.
associatedtype Indices : _Indexable, Sequence = DefaultIndices<Self>
associatedtype Indices = DefaultIndices<Self>
where Indices.Iterator.Element == Index,
Indices.Index == Index,
Indices.SubSequence == Indices
Indices.Index == Index

// FIXME(ABI)#100 (Recursive Protocol Constraints):
// associatedtype Indices : Collection
Expand Down
10 changes: 2 additions & 8 deletions stdlib/public/core/ExistentialCollection.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -426,14 +426,11 @@ internal class _AnyRandomAccessCollectionBox<Element>
@_fixed_layout
@_versioned
internal final class _${Kind}Box<S : ${Kind}> : _Any${Kind}Box<S.Iterator.Element>
% if Kind == 'Sequence':
where
S.SubSequence : ${Kind},
% if Kind == 'Sequence':
S.SubSequence.Iterator.Element == S.Iterator.Element,
S.SubSequence.SubSequence == S.SubSequence
% else:
S.SubSequence.Indices : ${Kind},
S.Indices : ${Kind}
% end
{
internal typealias Element = S.Iterator.Element
Expand Down Expand Up @@ -1040,10 +1037,7 @@ public struct ${Self}<Element>
where
// FIXME(ABI)#101 (Associated Types with where clauses): these constraints should be applied to
// associated types of Collection.
C.SubSequence : ${SubProtocol},
C.SubSequence.Iterator.Element == Element,
C.SubSequence.Indices : ${SubProtocol},
C.Indices : ${SubProtocol}
C.SubSequence.Iterator.Element == Element
{
// Traversal: ${Traversal}
// SubTraversal: ${SubTraversal}
Expand Down
14 changes: 2 additions & 12 deletions stdlib/public/core/Mirror.swift
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,7 @@ public struct Mirror {
children: C,
displayStyle: DisplayStyle? = nil,
ancestorRepresentation: AncestorRepresentation = .generated
) where
C.Iterator.Element == Child,
// FIXME(ABI)#47 (Associated Types with where clauses): these constraints should be applied to
// associated types of Collection.
C.SubSequence : Collection,
C.SubSequence.Indices : Collection,
C.Indices : Collection {
) where C.Iterator.Element == Child {

self.subjectType = Subject.self
self._makeSuperclassMirror = Mirror._superclassIterator(
Expand Down Expand Up @@ -267,11 +261,7 @@ public struct Mirror {
unlabeledChildren: C,
displayStyle: DisplayStyle? = nil,
ancestorRepresentation: AncestorRepresentation = .generated
) where
// FIXME(ABI)#48 (Associated Types with where clauses): these constraints should be applied to
// associated types of Collection.
C.SubSequence : Collection,
C.Indices : Collection {
) {

self.subjectType = Subject.self
self._makeSuperclassMirror = Mirror._superclassIterator(
Expand Down
11 changes: 3 additions & 8 deletions stdlib/public/core/MutableCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,9 @@ public protocol _MutableIndexable : _Indexable {
/// // Must be equivalent to:
/// a[i] = x
/// let y = x
public protocol MutableCollection : _MutableIndexable, Collection {
// FIXME(ABI)#181: should be constrained to MutableCollection
// (<rdar://problem/20715009> Implement recursive protocol
// constraints)
/// A collection that represents a contiguous subrange of the collection's
/// elements.
associatedtype SubSequence : Collection /*: MutableCollection*/
= MutableSlice<Self>
public protocol MutableCollection : _MutableIndexable, Collection
where SubSequence: MutableCollection {
associatedtype SubSequence = MutableSlice<Self>

/// Accesses the element at the specified position.
///
Expand Down
11 changes: 3 additions & 8 deletions stdlib/public/core/RandomAccessCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,15 @@ public protocol _RandomAccessIndexable : _BidirectionalIndexable {
/// `distance(from:to:)` methods with O(1) efficiency.
public protocol RandomAccessCollection :
_RandomAccessIndexable, BidirectionalCollection
where SubSequence: RandomAccessCollection, Indices: RandomAccessCollection
{
/// A collection that represents a contiguous subrange of the collection's
/// elements.
associatedtype SubSequence : _RandomAccessIndexable, BidirectionalCollection
= RandomAccessSlice<Self>
// FIXME(ABI)#102 (Recursive Protocol Constraints):
// associatedtype SubSequence : RandomAccessCollection
associatedtype SubSequence = RandomAccessSlice<Self>

/// A type that represents the indices that are valid for subscripting the
/// collection, in ascending order.
associatedtype Indices : _RandomAccessIndexable, BidirectionalCollection
= DefaultRandomAccessIndices<Self>
// FIXME(ABI)#103 (Recursive Protocol Constraints):
// associatedtype Indices : RandomAccessCollection
associatedtype Indices = DefaultRandomAccessIndices<Self>

/// The indices that are valid for subscripting the collection, in ascending
/// order.
Expand Down
2 changes: 1 addition & 1 deletion validation-test/stdlib/CollectionDiagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct CollectionWithBadSubSequence : Collection {
fatalError("unreachable")
}

// expected-note@+3 {{possibly intended match 'CollectionWithBadSubSequence.SubSequence' (aka 'OpaqueValue<Int8>') does not conform to 'Sequence'}}
// expected-note@+3 {{possibly intended match}}
// expected-note@+2 {{possibly intended match}}
// expected-note@+1 {{possibly intended match}}
typealias SubSequence = OpaqueValue<Int8>
Expand Down