From e5f893bc59ecf69e4d7f695a6fa1de80e12cca93 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 4 Sep 2017 22:28:40 -0700 Subject: [PATCH 01/12] [Sequence] Make Sequence.SubSequence conform to Sequence. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addressed ABI FIXME’s #4, #5, #104 and #105, making Sequence’s SubSequence conform to Sequence, with the same element type, and for which the SubSequence of a SubSequence is the same SubSequence. Fixes SR-318 / rdar://problem/31418206. --- .../CheckSequenceType.swift | 8 +------ .../StdlibUnittest/StdlibUnittest.swift.gyb | 14 ++----------- stdlib/public/core/Collection.swift | 7 ++----- .../core/ExistentialCollection.swift.gyb | 13 +++--------- stdlib/public/core/Sequence.swift | 21 ++++--------------- stdlib/public/core/SequenceWrapper.swift | 13 ++---------- 6 files changed, 14 insertions(+), 62 deletions(-) diff --git a/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift b/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift index e5ba6d949355d..721cba0a6a974 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift +++ b/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift @@ -1536,13 +1536,7 @@ extension TestSuite { resiliencyChecks: CollectionMisuseResiliencyChecks = .all ) where - SequenceWithEquatableElement.Iterator.Element : Equatable, - SequenceWithEquatableElement.SubSequence : Sequence, - SequenceWithEquatableElement.SubSequence.Iterator.Element - == SequenceWithEquatableElement.Iterator.Element, - S.SubSequence : Sequence, - S.SubSequence.Iterator.Element == S.Iterator.Element, - S.SubSequence.SubSequence == S.SubSequence { + SequenceWithEquatableElement.Iterator.Element : Equatable { var testNamePrefix = testNamePrefix diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb index ad172aae26095..c87401a0999aa 100644 --- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb +++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb @@ -378,11 +378,7 @@ public func expectTrapping( public func expectType(_: T.Type, _ x: inout T) {} public func expectEqualType(_: T.Type, _: T.Type) {} -public func expectSequenceType(_ x: X) -> X - where - X.SubSequence : Sequence, - X.SubSequence.Iterator.Element == X.Iterator.Element, - X.SubSequence.SubSequence == X.SubSequence { +public func expectSequenceType(_ x: X) -> X { return x } @@ -417,13 +413,7 @@ public func expectSequenceAssociatedTypes( sequenceType: X.Type, iteratorType: X.Iterator.Type, subSequenceType: X.SubSequence.Type -) where - // FIXME(ABI)#4 (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 : Sequence, - X.SubSequence.Iterator.Element == X.Iterator.Element, - // X.SubSequence.Indices == X.Indices, // FIXME(ABI)#5 (Recursive Protocol Constraints): can't have this constraint now. - X.SubSequence.SubSequence == X.SubSequence {} +) {} /// Check that all associated types of a `Collection` are what we expect them /// to be. diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift index fc932993f2173..9a53ec377dbde 100644 --- a/stdlib/public/core/Collection.swift +++ b/stdlib/public/core/Collection.swift @@ -651,12 +651,9 @@ public protocol Collection : _Indexable, Sequence /// collection, the subsequence should also conform to `Collection`. associatedtype SubSequence // FIXME(ABI) (Revert Where Clauses): remove these conformances: - : _IndexableBase, Sequence + : _IndexableBase = Slice - where SubSequence.SubSequence == SubSequence - // FIXME(ABI) (Revert Where Clauses): and this where clause: - , Element == SubSequence.Element - , SubSequence.Index == Index + where SubSequence.Index == Index // FIXME(ABI)#98 (Recursive Protocol Constraints): // FIXME(ABI)#99 (Associated Types with where clauses): diff --git a/stdlib/public/core/ExistentialCollection.swift.gyb b/stdlib/public/core/ExistentialCollection.swift.gyb index e803049c7653c..c7a140631218d 100644 --- a/stdlib/public/core/ExistentialCollection.swift.gyb +++ b/stdlib/public/core/ExistentialCollection.swift.gyb @@ -450,14 +450,10 @@ internal class _AnyRandomAccessCollectionBox @_fixed_layout @_versioned internal final class _${Kind}Box : _Any${Kind}Box +// FIXME(ABI) (Revert Where Clauses): apply all this only to Sequence: +% if Kind != 'Sequence': where S.SubSequence : ${Kind}, -// FIXME(ABI) (Revert Where Clauses): apply all this only to Sequence: -% if Kind == 'Sequence': - S.SubSequence.Element == S.Element, - S.SubSequence.SubSequence == S.SubSequence -// FIXME(ABI) (Revert Where Clauses): remove this else clause: -% else: S.SubSequence.Indices : ${Kind}, S.Indices : ${Kind} % end @@ -764,10 +760,7 @@ public struct AnySequence : Sequence { @_inlineable public init(_ base: S) where - S.Element == Element, - S.SubSequence : Sequence, - S.SubSequence.Element == Element, - S.SubSequence.SubSequence == S.SubSequence { + S.Element == Element { self._box = _SequenceBox(_base: base) } diff --git a/stdlib/public/core/Sequence.swift b/stdlib/public/core/Sequence.swift index d81cfa8b3bb78..61a52b59d37e4 100644 --- a/stdlib/public/core/Sequence.swift +++ b/stdlib/public/core/Sequence.swift @@ -331,19 +331,9 @@ public protocol Sequence { associatedtype Iterator : IteratorProtocol where Iterator.Element == Element /// A type that represents a subsequence of some of the sequence's elements. - associatedtype SubSequence - // FIXME(ABI)#104 (Recursive Protocol Constraints): - // FIXME(ABI)#105 (Associated Types with where clauses): - // associatedtype SubSequence : Sequence - // where - // Element == SubSequence.Element, - // SubSequence.SubSequence == SubSequence - // - // ( Implement recursive protocol - // constraints) - // - // These constraints allow processing collections in generic code by - // repeatedly slicing them in a loop. + associatedtype SubSequence : Sequence + where Element == SubSequence.Element, + SubSequence.SubSequence == SubSequence /// Returns an iterator over the elements of this sequence. func makeIterator() -> Iterator @@ -1194,10 +1184,7 @@ extension Sequence where Element : Equatable { } } -extension Sequence where - SubSequence : Sequence, - SubSequence.Element == Element, - SubSequence.SubSequence == SubSequence { +extension Sequence { /// Returns a subsequence containing all but the given number of initial /// elements. diff --git a/stdlib/public/core/SequenceWrapper.swift b/stdlib/public/core/SequenceWrapper.swift index a06981f320165..f89c407cfaf12 100644 --- a/stdlib/public/core/SequenceWrapper.swift +++ b/stdlib/public/core/SequenceWrapper.swift @@ -19,7 +19,7 @@ @_show_in_interface public // @testable protocol _SequenceWrapper : Sequence { - associatedtype Base : Sequence + associatedtype Base : Sequence where Base.Element == Element associatedtype Iterator = Base.Iterator associatedtype SubSequence = Base.SubSequence @@ -55,7 +55,7 @@ extension _SequenceWrapper where Iterator == Base.Iterator { } } -extension _SequenceWrapper where Element == Base.Element { +extension _SequenceWrapper { @_inlineable // FIXME(sil-serialize-all) public func map( _ transform: (Element) throws -> T @@ -106,10 +106,6 @@ extension _SequenceWrapper where SubSequence == Base.SubSequence { public func suffix(_ maxLength: Int) -> SubSequence { return _base.suffix(maxLength) } -} - -extension _SequenceWrapper - where SubSequence == Base.SubSequence, Element == Base.Element { @_inlineable // FIXME(sil-serialize-all) public func drop( @@ -125,11 +121,6 @@ extension _SequenceWrapper return try _base.prefix(while: predicate) } - @_inlineable // FIXME(sil-serialize-all) - public func suffix(_ maxLength: Int) -> SubSequence { - return _base.suffix(maxLength) - } - @_inlineable // FIXME(sil-serialize-all) public func split( maxSplits: Int, omittingEmptySubsequences: Bool, From 6b51806b54d0bba32298cd945b04eab737d3bef0 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 13 Sep 2017 10:53:34 -0700 Subject: [PATCH 02/12] [SE-0157] Make *Collection.SubSequence conform to corresponding *Collection. Introduce (recursive) constraints that make the *Collection constraint of SubSequence match that of its enclosing *Collection, e.g., MutableCollection.SubSequence conforms to MutableCollection. Fixes rdar://problem/20715031 and more of SR-3453. --- .../CheckCollectionInstance.swift.gyb | 10 +++------- .../CheckCollectionType.swift.gyb | 6 ------ .../CheckMutableCollectionType.swift.gyb | 3 --- .../CheckRangeReplaceableCollectionType.swift | 4 +--- .../StdlibUnittest/StdlibUnittest.swift.gyb | 16 --------------- .../public/core/BidirectionalCollection.swift | 4 +--- stdlib/public/core/Collection.swift | 20 ++++++++----------- .../core/ExistentialCollection.swift.gyb | 8 +++----- stdlib/public/core/Mirror.swift | 4 ++-- stdlib/public/core/MutableCollection.swift | 7 +------ .../public/core/RandomAccessCollection.swift | 14 +++++-------- .../core/RangeReplaceableCollection.swift.gyb | 8 +------- stdlib/public/core/Reverse.swift | 3 +++ stdlib/public/core/Slice.swift.gyb | 10 ++++------ test/Generics/requirement_inference.swift | 1 - 15 files changed, 32 insertions(+), 86 deletions(-) diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb index 3bb4871b296ed..f4dea7b547809 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb +++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb @@ -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, @@ -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( @@ -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) @@ -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) diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb index e0886c4dbdfbe..4b3aa26db5ce9 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb +++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb @@ -471,15 +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() diff --git a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb index 84ef5bf4650f2..d0136a009b2dc 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb +++ b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb @@ -121,7 +121,6 @@ extension TestSuite { isFixedLengthCollection: Bool, collectionIsBidirectional: Bool = false ) where - C.SubSequence : MutableCollection, C.Indices : Collection, CollectionWithEquatableElement.Iterator.Element : Equatable, CollectionWithComparableElement.Iterator.Element : Comparable { @@ -776,7 +775,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 { @@ -922,7 +920,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 { diff --git a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift index 14363c64c71c1..ad1bdd63b5530 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift +++ b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift @@ -462,10 +462,8 @@ 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 diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb index c87401a0999aa..4c0d3e9b7b229 100644 --- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb +++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb @@ -388,10 +388,6 @@ public func expect${Mutable}CollectionType( ) 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 @@ -425,10 +421,6 @@ public func expectCollectionAssociatedTypes( 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 @@ -441,10 +433,6 @@ public func expectBidirectionalCollectionAssociatedTypes /// A type that represents the indices that are valid for subscripting the diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift index 9a53ec377dbde..b21fce7debfb9 100644 --- a/stdlib/public/core/Collection.swift +++ b/stdlib/public/core/Collection.swift @@ -622,8 +622,8 @@ public struct IndexingIterator< /// the number of contained elements, accessing its `count` property is an /// O(*n*) operation. public protocol Collection : _Indexable, Sequence -// FIXME(ABI) (Revert Where Clauses): Restore these -// where SubSequence: Collection, Indices: Collection, +// FIXME(ABI) (Revert Where Clauses): Restore this +// where Indices: Collection, { /// A type that represents the number of steps between a pair of /// indices. @@ -649,17 +649,13 @@ 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 - // FIXME(ABI) (Revert Where Clauses): remove these conformances: - : _IndexableBase - = Slice - where SubSequence.Index == Index - - // FIXME(ABI)#98 (Recursive Protocol Constraints): + associatedtype SubSequence : Collection = Slice + where SubSequence.Index == Index + // FIXME(ABI)#99 (Associated Types with where clauses): - // associatedtype SubSequence : Collection - // where - // SubSequence.Indices == Indices, + // where SubSequence.Indices == Indices, + + // // ( Implement recursive protocol // constraints) diff --git a/stdlib/public/core/ExistentialCollection.swift.gyb b/stdlib/public/core/ExistentialCollection.swift.gyb index c7a140631218d..31ebc114b7fb1 100644 --- a/stdlib/public/core/ExistentialCollection.swift.gyb +++ b/stdlib/public/core/ExistentialCollection.swift.gyb @@ -451,9 +451,8 @@ internal class _AnyRandomAccessCollectionBox @_versioned internal final class _${Kind}Box : _Any${Kind}Box // FIXME(ABI) (Revert Where Clauses): apply all this only to Sequence: -% if Kind != 'Sequence': +% if Kind != 'Sequence' and Kind != 'Collection': where - S.SubSequence : ${Kind}, S.SubSequence.Indices : ${Kind}, S.Indices : ${Kind} % end @@ -1034,8 +1033,8 @@ protocol _AnyCollectionProtocol : Collection { public struct ${Self} : _AnyCollectionProtocol, ${SelfProtocol} { -// public typealias Indices -// = Default${Traversal.replace('Forward', '')}Indices<${Self}> + public typealias Indices + = Default${Traversal.replace('Forward', '')}Indices<${Self}> public typealias Iterator = AnyIterator @@ -1056,7 +1055,6 @@ public struct ${Self} public init(_ base: C) where // FIXME(ABI) (Revert Where Clauses): remove next 3 lines - C.SubSequence : ${SubProtocol}, C.SubSequence.Indices : ${SubProtocol}, C.Indices : ${SubProtocol}, // FIXME(ABI)#101 (Associated Types with where clauses): these constraints diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift index cdb6ac33da3bf..fb81db71e5608 100644 --- a/stdlib/public/core/Mirror.swift +++ b/stdlib/public/core/Mirror.swift @@ -226,7 +226,7 @@ public struct Mirror { ancestorRepresentation: AncestorRepresentation = .generated ) where C.Element == Child // FIXME(ABI) (Revert Where Clauses): Remove these - , C.SubSequence : Collection, C.SubSequence.Indices : Collection, C.Indices : Collection + , C.SubSequence.Indices : Collection, C.Indices : Collection { self.subjectType = Subject.self @@ -277,7 +277,7 @@ public struct Mirror { ancestorRepresentation: AncestorRepresentation = .generated ) // FIXME(ABI) (Revert Where Clauses): Remove these two clauses - where C.SubSequence : Collection, C.Indices : Collection + where C.Indices : Collection { self.subjectType = Subject.self diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift index e2cf4372252f4..87031e749288a 100644 --- a/stdlib/public/core/MutableCollection.swift +++ b/stdlib/public/core/MutableCollection.swift @@ -197,13 +197,8 @@ public protocol _MutableIndexable : _Indexable { /// a[i] = x /// let y = x public protocol MutableCollection : _MutableIndexable, Collection -// FIXME(ABI) (Revert Where Clauses): restore this: -// where SubSequence: MutableCollection { - associatedtype SubSequence - // FIXME(ABI) (Revert Where Clauses): remove this conformance: - : Collection - = MutableSlice + associatedtype SubSequence : MutableCollection = MutableSlice /// Accesses the element at the specified position. /// diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift index fcbfa39005227..411bb31fb4247 100644 --- a/stdlib/public/core/RandomAccessCollection.swift +++ b/stdlib/public/core/RandomAccessCollection.swift @@ -48,22 +48,18 @@ public protocol _RandomAccessIndexable : _BidirectionalIndexable { /// `distance(from:to:)` methods with O(1) efficiency. public protocol RandomAccessCollection : _RandomAccessIndexable, BidirectionalCollection -// FIXME(ABI) (Revert Where Clauses): Restore this: -// where SubSequence: RandomAccessCollection, Indices: RandomAccessCollection { /// A collection that represents a contiguous subrange of the collection's /// elements. - associatedtype SubSequence - // FIXME(ABI) (Revert Where Clauses): Remove these two constraints: - : _RandomAccessIndexable, BidirectionalCollection - = RandomAccessSlice + associatedtype SubSequence : RandomAccessCollection + = RandomAccessSlice /// A type that represents the indices that are valid for subscripting the /// collection, in ascending order. associatedtype Indices - // FIXME(ABI) (Revert Where Clauses): Remove these two constraints: - : _RandomAccessIndexable, BidirectionalCollection - = DefaultRandomAccessIndices + // FIXME(ABI) (Revert Where Clauses): Remove these two constraints: + : _RandomAccessIndexable, BidirectionalCollection + = DefaultRandomAccessIndices /// The indices that are valid for subscripting the collection, in ascending /// order. diff --git a/stdlib/public/core/RangeReplaceableCollection.swift.gyb b/stdlib/public/core/RangeReplaceableCollection.swift.gyb index c9a7b652d12c4..53d99403f8a2a 100644 --- a/stdlib/public/core/RangeReplaceableCollection.swift.gyb +++ b/stdlib/public/core/RangeReplaceableCollection.swift.gyb @@ -244,8 +244,7 @@ public protocol _RangeReplaceableIndexable : _Indexable { public protocol RangeReplaceableCollection : _RangeReplaceableIndexable, Collection { - // FIXME(ABI)#165 (Recursive Protocol Constraints): should require `RangeReplaceableCollection`. - associatedtype SubSequence : _RangeReplaceableIndexable /*: RangeReplaceableCollection*/ + associatedtype SubSequence : RangeReplaceableCollection = RangeReplaceableSlice //===--- Fundamental Requirements ---------------------------------------===// @@ -813,7 +812,6 @@ extension RangeReplaceableCollection { % for capability in ['', 'Bidirectional', 'RandomAccess']: % if capability: extension RangeReplaceableCollection where - Self: ${capability}Collection, Self.SubSequence == RangeReplaceable${capability}Slice { @_inlineable // FIXME(sil-serialize-all) public subscript(bounds: Range) @@ -824,10 +822,6 @@ extension RangeReplaceableCollection where % end extension RangeReplaceableCollection where - Self: MutableCollection, -% if capability: - Self: ${capability}Collection, -% end Self.SubSequence == MutableRangeReplaceable${capability}Slice { @_inlineable // FIXME(sil-serialize-all) diff --git a/stdlib/public/core/Reverse.swift b/stdlib/public/core/Reverse.swift index 28c20482a4756..98bfd52aecbbb 100644 --- a/stdlib/public/core/Reverse.swift +++ b/stdlib/public/core/Reverse.swift @@ -380,6 +380,9 @@ public struct ReversedRandomAccessCollection< public typealias IndexDistance = Base.IndexDistance + public typealias Indices = + DefaultRandomAccessIndices> + /// A type that provides the sequence's iteration interface and /// encapsulates its iteration state. public typealias Iterator = IndexingIterator< diff --git a/stdlib/public/core/Slice.swift.gyb b/stdlib/public/core/Slice.swift.gyb index 68a80672b1244..9665e51146dea 100644 --- a/stdlib/public/core/Slice.swift.gyb +++ b/stdlib/public/core/Slice.swift.gyb @@ -15,6 +15,7 @@ from gyb_stdlib_support import ( TRAVERSALS, collectionForTraversal, + defaultIndicesForTraversal, sliceTypeName, protocolsForCollectionFeatures ) @@ -96,13 +97,9 @@ def get_slice_doc_comment(Self): % for Mutable in [ False, True ]: % for RangeReplaceable in [ False, True ]: % Self = sliceTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable) -% BaseRequirements = ['_' + collectionForTraversal(Traversal).replace('Collection', 'Indexable')] -% if Mutable: -% BaseRequirements.append('_MutableIndexable') -% if RangeReplaceable: -% BaseRequirements.append('_RangeReplaceableIndexable') -% BaseRequirements = ' & '.join(BaseRequirements) +% BaseRequirements = ' & '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)) % SelfProtocols = ', '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)) +% Indices = defaultIndicesForTraversal(Traversal) ${get_slice_doc_comment(Self)} % if Mutable: @@ -119,6 +116,7 @@ public struct ${Self} public typealias Index = Base.Index public typealias IndexDistance = Base.IndexDistance + public typealias Indices = ${Indices}<${Self}> public var _startIndex: Index public var _endIndex: Index diff --git a/test/Generics/requirement_inference.swift b/test/Generics/requirement_inference.swift index e96db636179fa..128a1ed92ce6e 100644 --- a/test/Generics/requirement_inference.swift +++ b/test/Generics/requirement_inference.swift @@ -168,7 +168,6 @@ func sameTypeConcrete2(_: T) where T.B : X3, T.C == T.B, T.C == X3 // CHECK-LABEL: RangeReplaceableCollection // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : MutableCollection, τ_0_0 : RangeReplaceableCollection, τ_0_0.SubSequence == MutableRangeReplaceableSlice<τ_0_0>> extension RangeReplaceableCollection where - Self: MutableCollection, Self.SubSequence == MutableRangeReplaceableSlice { func f() { } From 44572644d39e5be10c2e2969d4ae51aff3e20e97 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 13 Sep 2017 13:28:15 -0700 Subject: [PATCH 03/12] [Unit test library] Remove redundant constraints. --- .../CheckRangeReplaceableCollectionType.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift index ad1bdd63b5530..901f5c0c41380 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift +++ b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift @@ -1178,7 +1178,6 @@ self.test("\(testNamePrefix).OperatorPlus") { resiliencyChecks: CollectionMisuseResiliencyChecks = .all, outOfBoundsIndexOffset: Int = 1 ) where - C.SubSequence : BidirectionalCollection & RangeReplaceableCollection, C.Indices : BidirectionalCollection, CollectionWithEquatableElement.Iterator.Element : Equatable { @@ -1300,7 +1299,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 { From 52eb618abcb1da7f896bce14f1d9e193738df315 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 13 Sep 2017 20:13:04 -0700 Subject: [PATCH 04/12] [Collections] Constrain Indices type to Collection. Make the Indices types conform to the appropriate Collection protocol: * Collection.Indices: Collection * BidirectionalCollection.Indices: BidirectionalCollection * RandomAccessCollection.Indices: RandomAccessCollection --- .../CheckCollectionType.swift.gyb | 1 - .../CheckMutableCollectionType.swift.gyb | 3 --- .../CheckRangeReplaceableCollectionType.swift | 3 --- .../CheckRangeReplaceableSliceType.swift | 3 --- .../StdlibUnittest/StdlibUnittest.swift.gyb | 14 ++++---------- stdlib/public/core/BidirectionalCollection.swift | 4 +--- stdlib/public/core/Collection.swift | 15 +++------------ .../public/core/ExistentialCollection.swift.gyb | 15 ++------------- stdlib/public/core/Mirror.swift | 4 ---- stdlib/public/core/RandomAccessCollection.swift | 6 ++---- 10 files changed, 12 insertions(+), 56 deletions(-) diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb index 4b3aa26db5ce9..9db5c1fe8f56f 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb +++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb @@ -474,7 +474,6 @@ internal enum _SubSequenceSubscriptOnRangeMode { return ''' C : %(protocol)s, CollectionWithEquatableElement : %(protocol)s, - C.Indices : %(protocol)s, CollectionWithEquatableElement.Iterator.Element : Equatable ''' % locals() diff --git a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb index d0136a009b2dc..0674c8dc6488d 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb +++ b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb @@ -121,7 +121,6 @@ extension TestSuite { isFixedLengthCollection: Bool, collectionIsBidirectional: Bool = false ) where - C.Indices : Collection, CollectionWithEquatableElement.Iterator.Element : Equatable, CollectionWithComparableElement.Iterator.Element : Comparable { @@ -775,7 +774,6 @@ self.test("\(testNamePrefix).partition/InvalidOrderings") { withUnsafeMutableBufferPointerIsSupported: Bool, isFixedLengthCollection: Bool ) where - C.Indices : BidirectionalCollection, CollectionWithEquatableElement.Iterator.Element : Equatable, CollectionWithComparableElement.Iterator.Element : Comparable { @@ -920,7 +918,6 @@ self.test("\(testNamePrefix).partition/DispatchesThrough_withUnsafeMutableBuffer withUnsafeMutableBufferPointerIsSupported: Bool, isFixedLengthCollection: Bool ) where - C.Indices : RandomAccessCollection, CollectionWithEquatableElement.Iterator.Element : Equatable, CollectionWithComparableElement.Iterator.Element : Comparable { diff --git a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift index 901f5c0c41380..245f486a4a3a8 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift +++ b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift @@ -462,7 +462,6 @@ extension TestSuite { outOfBoundsIndexOffset: Int = 1, collectionIsBidirectional: Bool = false ) where - C.Indices : Collection, CollectionWithEquatableElement.Iterator.Element : Equatable { var testNamePrefix = testNamePrefix @@ -1178,7 +1177,6 @@ self.test("\(testNamePrefix).OperatorPlus") { resiliencyChecks: CollectionMisuseResiliencyChecks = .all, outOfBoundsIndexOffset: Int = 1 ) where - C.Indices : BidirectionalCollection, CollectionWithEquatableElement.Iterator.Element : Equatable { var testNamePrefix = testNamePrefix @@ -1299,7 +1297,6 @@ self.test("\(testNamePrefix).removeLast(n: Int)/whereIndexIsBidirectional/remove resiliencyChecks: CollectionMisuseResiliencyChecks = .all, outOfBoundsIndexOffset: Int = 1 ) where - C.Indices : RandomAccessCollection, CollectionWithEquatableElement.Iterator.Element : Equatable { var testNamePrefix = testNamePrefix diff --git a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift index fb10e306fed93..28a802ee73e14 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift +++ b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift @@ -33,7 +33,6 @@ extension TestSuite { collectionIsBidirectional: Bool = false ) where C.SubSequence == C, - C.Indices : Collection, CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement, CollectionWithEquatableElement.Iterator.Element : Equatable { @@ -165,7 +164,6 @@ extension TestSuite { outOfBoundsIndexOffset: Int = 1 ) where C.SubSequence == C, - C.Indices : BidirectionalCollection, CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement, CollectionWithEquatableElement.Iterator.Element : Equatable { @@ -310,7 +308,6 @@ extension TestSuite { outOfBoundsIndexOffset: Int = 1 ) where C.SubSequence == C, - C.Indices : RandomAccessCollection, CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement, CollectionWithEquatableElement.Iterator.Element : Equatable { diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb index 4c0d3e9b7b229..51fe0101a7482 100644 --- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb +++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb @@ -385,10 +385,7 @@ public func expectSequenceType(_ x: X) -> X { % for Mutable in ['', 'Mutable']: public func expect${Mutable}CollectionType( _ 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. - X.Indices : Collection {} +) {} % end /// A slice is a `Collection` that when sliced returns an instance of @@ -420,8 +417,7 @@ public func expectCollectionAssociatedTypes( indexType: X.Index.Type, indexDistanceType: X.IndexDistance.Type, indicesType: X.Indices.Type -) where - X.Indices : Collection {} +) {} /// Check that all associated types of a `BidirectionalCollection` are what we /// expect them to be. @@ -432,8 +428,7 @@ public func expectBidirectionalCollectionAssociatedTypes /// The indices that are valid for subscripting the collection, in ascending diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift index b21fce7debfb9..5dafda1b6cc4c 100644 --- a/stdlib/public/core/Collection.swift +++ b/stdlib/public/core/Collection.swift @@ -711,20 +711,11 @@ public protocol Collection : _Indexable, Sequence /// A type that represents the indices that are valid for subscripting the /// collection, in ascending order. - associatedtype Indices - // FIXME(ABI) (Revert Where Clauses): Remove these two conformances - : _Indexable, Sequence - = DefaultIndices + associatedtype Indices : Collection = DefaultIndices where Indices.Element == Index, - Indices.Index == Index - // FIXME(ABI) (Revert Where Clauses): Remove this where clause - , Indices.SubSequence == Indices + Indices.Index == Index, + Indices.SubSequence == Indices - // FIXME(ABI)#100 (Recursive Protocol Constraints): - // associatedtype Indices : Collection - // where - // = DefaultIndices - /// The indices that are valid for subscripting the collection, in ascending /// order. /// diff --git a/stdlib/public/core/ExistentialCollection.swift.gyb b/stdlib/public/core/ExistentialCollection.swift.gyb index 31ebc114b7fb1..709f167caa035 100644 --- a/stdlib/public/core/ExistentialCollection.swift.gyb +++ b/stdlib/public/core/ExistentialCollection.swift.gyb @@ -450,12 +450,6 @@ internal class _AnyRandomAccessCollectionBox @_fixed_layout @_versioned internal final class _${Kind}Box : _Any${Kind}Box -// FIXME(ABI) (Revert Where Clauses): apply all this only to Sequence: -% if Kind != 'Sequence' and Kind != 'Collection': - where - S.SubSequence.Indices : ${Kind}, - S.Indices : ${Kind} -% end { internal typealias Element = S.Element @@ -1053,13 +1047,8 @@ public struct ${Self} /// - Complexity: O(1). @_inlineable public init(_ base: C) - where - // FIXME(ABI) (Revert Where Clauses): remove next 3 lines - C.SubSequence.Indices : ${SubProtocol}, - C.Indices : ${SubProtocol}, - // FIXME(ABI)#101 (Associated Types with where clauses): these constraints - // should be applied to associated types of Collection. - C.SubSequence.Element == Element + where + C.Element == Element { // Traversal: ${Traversal} // SubTraversal: ${SubTraversal} diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift index fb81db71e5608..95079ce5bae25 100644 --- a/stdlib/public/core/Mirror.swift +++ b/stdlib/public/core/Mirror.swift @@ -225,8 +225,6 @@ public struct Mirror { displayStyle: DisplayStyle? = nil, ancestorRepresentation: AncestorRepresentation = .generated ) where C.Element == Child - // FIXME(ABI) (Revert Where Clauses): Remove these - , C.SubSequence.Indices : Collection, C.Indices : Collection { self.subjectType = Subject.self @@ -276,8 +274,6 @@ public struct Mirror { displayStyle: DisplayStyle? = nil, ancestorRepresentation: AncestorRepresentation = .generated ) - // FIXME(ABI) (Revert Where Clauses): Remove these two clauses - where C.Indices : Collection { self.subjectType = Subject.self diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift index 411bb31fb4247..f18dcca16df82 100644 --- a/stdlib/public/core/RandomAccessCollection.swift +++ b/stdlib/public/core/RandomAccessCollection.swift @@ -56,10 +56,8 @@ public protocol RandomAccessCollection : /// A type that represents the indices that are valid for subscripting the /// collection, in ascending order. - associatedtype Indices - // FIXME(ABI) (Revert Where Clauses): Remove these two constraints: - : _RandomAccessIndexable, BidirectionalCollection - = DefaultRandomAccessIndices + associatedtype Indices : RandomAccessCollection + = DefaultRandomAccessIndices /// The indices that are valid for subscripting the collection, in ascending /// order. From af48bdc539315fb4572f7acad3cb837614c21bb0 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 13 Sep 2017 23:20:01 -0700 Subject: [PATCH 05/12] Use Collection protocols in IndexingIterator and Default*Indices constraints. Eliminates a few explicit uses of the Indexable protocols. --- stdlib/public/core/ArrayBufferProtocol.swift | 5 +---- stdlib/public/core/Collection.swift | 7 +------ stdlib/public/core/Indices.swift.gyb | 5 +---- test/Generics/requirement_inference.swift | 2 +- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/stdlib/public/core/ArrayBufferProtocol.swift b/stdlib/public/core/ArrayBufferProtocol.swift index 74d993a765680..7ac8aa38dfa77 100644 --- a/stdlib/public/core/ArrayBufferProtocol.swift +++ b/stdlib/public/core/ArrayBufferProtocol.swift @@ -16,10 +16,7 @@ internal protocol _ArrayBufferProtocol : MutableCollection, RandomAccessCollection { - associatedtype Indices - // FIXME(ABI) (Revert Where Clauses): Remove this conformance - : RandomAccessCollection - = CountableRange + associatedtype Indices = CountableRange /// Create an empty buffer. init() diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift index 5dafda1b6cc4c..c2a399f1eb0fc 100644 --- a/stdlib/public/core/Collection.swift +++ b/stdlib/public/core/Collection.swift @@ -356,10 +356,7 @@ public protocol _Indexable : _IndexableBase { /// // Prints "20.0" @_fixed_layout public struct IndexingIterator< - Elements : _IndexableBase - // FIXME(ABI)#97 (Recursive Protocol Constraints): - // Should be written as: - // Elements : Collection + Elements : Collection > : IteratorProtocol, Sequence { @_inlineable @@ -654,8 +651,6 @@ public protocol Collection : _Indexable, Sequence // FIXME(ABI)#99 (Associated Types with where clauses): // where SubSequence.Indices == Indices, - - // // ( Implement recursive protocol // constraints) diff --git a/stdlib/public/core/Indices.swift.gyb b/stdlib/public/core/Indices.swift.gyb index 5a5d8f131d6e1..e6ecc55e120da 100644 --- a/stdlib/public/core/Indices.swift.gyb +++ b/stdlib/public/core/Indices.swift.gyb @@ -31,10 +31,7 @@ from gyb_stdlib_support import ( /// A collection of indices for an arbitrary ${collection}. @_fixed_layout public struct ${Self}< - Elements : _${collectionForTraversal(Traversal).replace('Collection', 'Indexable')} - // FIXME(ABI)#43 (Recursive Protocol Constraints): - // Elements : Collection - // rdar://problem/20531108 + Elements : ${collectionForTraversal(Traversal)} > : ${collectionForTraversal(Traversal)} { // FIXME(compiler limitation): this typealias should be inferred. diff --git a/test/Generics/requirement_inference.swift b/test/Generics/requirement_inference.swift index 128a1ed92ce6e..1342d298a5a8e 100644 --- a/test/Generics/requirement_inference.swift +++ b/test/Generics/requirement_inference.swift @@ -176,7 +176,7 @@ extension RangeReplaceableCollection where // CHECK-LABEL: X14.recursiveConcreteSameType // CHECK: Generic signature: > // CHECK-NEXT: Canonical generic signature: <τ_0_0, τ_1_0 where τ_0_0 == CountableRange> -struct X14 where T.Iterator == IndexingIterator { +struct X14 where T.Iterator == IndexingIterator { func recursiveConcreteSameType(_: V) where T == CountableRange { } } From 9d2c9be04ead6d9df513c140d261a2071b702897 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 14 Sep 2017 09:32:56 -0700 Subject: [PATCH 06/12] Remove already-completed or separate-discussed ABI FIXMEs. --- stdlib/public/core/BidirectionalCollection.swift | 2 -- stdlib/public/core/Collection.swift | 11 ----------- 2 files changed, 13 deletions(-) diff --git a/stdlib/public/core/BidirectionalCollection.swift b/stdlib/public/core/BidirectionalCollection.swift index b52f731380d2f..18fa13f5955f7 100644 --- a/stdlib/public/core/BidirectionalCollection.swift +++ b/stdlib/public/core/BidirectionalCollection.swift @@ -66,8 +66,6 @@ public protocol _BidirectionalIndexable : _Indexable { /// - If `i > c.startIndex && i <= c.endIndex` /// `c.index(after: c.index(before: i)) == i`. public protocol BidirectionalCollection : _BidirectionalIndexable, Collection -// FIXME(ABI) (Revert Where Clauses): Restore these -// where SubSequence: BidirectionalCollection, Indices: BidirectionalCollection { // TODO: swift-3-indexing-model - replaces functionality in BidirectionalIndex diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift index c2a399f1eb0fc..96b54cbd3e549 100644 --- a/stdlib/public/core/Collection.swift +++ b/stdlib/public/core/Collection.swift @@ -619,8 +619,6 @@ public struct IndexingIterator< /// the number of contained elements, accessing its `count` property is an /// O(*n*) operation. public protocol Collection : _Indexable, Sequence -// FIXME(ABI) (Revert Where Clauses): Restore this -// where Indices: Collection, { /// A type that represents the number of steps between a pair of /// indices. @@ -649,15 +647,6 @@ public protocol Collection : _Indexable, Sequence associatedtype SubSequence : Collection = Slice where SubSequence.Index == Index - // FIXME(ABI)#99 (Associated Types with where clauses): - // where SubSequence.Indices == Indices, - // - // ( Implement recursive protocol - // constraints) - // - // These constraints allow processing collections in generic code by - // repeatedly slicing them in a loop. - /// Accesses the element at the specified position. /// /// The following example accesses an element of an array through its From 31ad22df45b2bc12a10e409d53b457d00dff6280 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 14 Sep 2017 09:33:17 -0700 Subject: [PATCH 07/12] Make Numeric.Magnitude conform to Numeric --- stdlib/public/core/Integers.swift.gyb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb index f9e2b91750bed..a453704ac2c81 100644 --- a/stdlib/public/core/Integers.swift.gyb +++ b/stdlib/public/core/Integers.swift.gyb @@ -989,11 +989,9 @@ public protocol Numeric : Equatable, ExpressibleByIntegerLiteral { /// - Parameter source: A value to convert to this type. init?(exactly source: T) - // FIXME(ABI)#44 (Recursive Protocol Constraints): should be just - // Numeric, Comparable /// A type that can represent the absolute value of any possible value of the /// conforming type. - associatedtype Magnitude : Comparable, ExpressibleByIntegerLiteral + associatedtype Magnitude : Comparable, Numeric /// The magnitude of this value. /// From fb253b182af71aa8a4843d0b50b3af61a1ce073b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 14 Sep 2017 10:21:47 -0700 Subject: [PATCH 08/12] Use a more efficient SubSequence type for lazy map and filter. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 #28 and #46. --- stdlib/public/core/Filter.swift.gyb | 20 +++++--------------- stdlib/public/core/Map.swift.gyb | 20 +++++--------------- validation-test/stdlib/Lazy.swift.gyb | 15 +++++---------- 3 files changed, 15 insertions(+), 40 deletions(-) diff --git a/stdlib/public/core/Filter.swift.gyb b/stdlib/public/core/Filter.swift.gyb index 7387465ff95df..33895019599c0 100644 --- a/stdlib/public/core/Filter.swift.gyb +++ b/stdlib/public/core/Filter.swift.gyb @@ -12,8 +12,7 @@ %{ from gyb_stdlib_support import ( - collectionForTraversal, - sliceTypeName + collectionForTraversal ) }% @@ -115,7 +114,6 @@ public typealias LazyFilterIndex = Base.Index % for Traversal in ['Forward', 'Bidirectional']: % Self = "LazyFilter" + collectionForTraversal(Traversal) -% Slice = sliceTypeName(traversal=Traversal, mutable=False, rangeReplaceable=False) /// A lazy `Collection` wrapper that includes the elements of an /// underlying collection that satisfy a predicate. @@ -224,9 +222,11 @@ public struct ${Self}< return _base[position] } + public typealias SubSequence = ${Self} + @_inlineable // FIXME(sil-serialize-all) - public subscript(bounds: Range) -> ${Slice}<${Self}> { - return ${Slice}(base: self, bounds: bounds) + public subscript(bounds: Range) -> SubSequence { + return SubSequence(_base: _base[bounds], _predicate) } // Any estimate of the number of elements that pass `_predicate` requires @@ -247,16 +247,6 @@ public struct ${Self}< return _copySequenceToContiguousArray(self) } - // FIXME(ABI)#28 (Associated Types with where clauses): we actually want to add: - // - // typealias SubSequence = ${Self} - // - // so that all slicing optimizations of the base collection can kick in. - // - // We can't do that right now though, because that would force a lot of - // constraints on `Base.SubSequence`, limiting the possible contexts where - // the `.lazy.filter` API can be used. - /// Returns an iterator over the elements of this sequence. /// /// - Complexity: O(1). diff --git a/stdlib/public/core/Map.swift.gyb b/stdlib/public/core/Map.swift.gyb index c665382a27f16..2e71bb26070e2 100644 --- a/stdlib/public/core/Map.swift.gyb +++ b/stdlib/public/core/Map.swift.gyb @@ -13,8 +13,7 @@ %{ from gyb_stdlib_support import ( TRAVERSALS, - collectionForTraversal, - sliceTypeName + collectionForTraversal ) }% @@ -104,7 +103,6 @@ public struct LazyMapSequence % for Traversal in TRAVERSALS: % Self = "LazyMap" + collectionForTraversal(Traversal) -% Slice = sliceTypeName(traversal=Traversal, mutable=False, rangeReplaceable=False) /// A `Collection` whose elements consist of those in a `Base` /// `Collection` passed through a transform function returning `Element`. @@ -150,21 +148,13 @@ public struct ${Self}< return _transform(_base[position]) } + public typealias SubSequence = ${Self} + @_inlineable - public subscript(bounds: Range) -> ${Slice}<${Self}> { - return ${Slice}(base: self, bounds: bounds) + public subscript(bounds: Range) -> SubSequence { + return SubSequence(_base: _base[bounds], transform: _transform) } - // FIXME(ABI)#46 (Associated Types with where clauses): we actually want to add: - // - // typealias SubSequence = ${Self} - // - // so that all slicing optimizations of the base collection can kick in. - // - // We can't do that right now though, because that would force a lot of - // constraints on `Base.SubSequence`, limiting the possible contexts where - // the `.lazy.map` API can be used. - public typealias IndexDistance = Base.IndexDistance public typealias Indices = Base.Indices diff --git a/validation-test/stdlib/Lazy.swift.gyb b/validation-test/stdlib/Lazy.swift.gyb index b91833b189fa2..56c716bd776ec 100644 --- a/validation-test/stdlib/Lazy.swift.gyb +++ b/validation-test/stdlib/Lazy.swift.gyb @@ -874,8 +874,7 @@ tests.test("LazyMapCollection/AssociatedTypes") { expectCollectionAssociatedTypes( collectionType: Subject.self, iteratorType: LazyMapIterator>.self, - // FIXME(ABI)#77 (Associated Types with where clauses): SubSequence should be `LazyMapCollection`. - subSequenceType: Slice.self, + subSequenceType: LazyMapCollection>.self, indexType: Base.Index.self, indexDistanceType: Base.IndexDistance.self, indicesType: Base.Indices.self) @@ -887,8 +886,7 @@ tests.test("LazyMapBidirectionalCollection/AssociatedTypes") { expectBidirectionalCollectionAssociatedTypes( collectionType: Subject.self, iteratorType: LazyMapIterator>.self, - // FIXME(ABI)#78 (Associated Types with where clauses): SubSequence should be `LazyMapBidirectionalCollection`. - subSequenceType: BidirectionalSlice.self, + subSequenceType: LazyMapBidirectionalCollection>.self, indexType: Base.Index.self, indexDistanceType: Base.IndexDistance.self, indicesType: Base.Indices.self) @@ -900,8 +898,7 @@ tests.test("LazyMapRandomAccessCollection/AssociatedTypes") { expectRandomAccessCollectionAssociatedTypes( collectionType: Subject.self, iteratorType: LazyMapIterator>.self, - // FIXME(ABI)#79 (Associated Types with where clauses): SubSequence should be `LazyMapRandomAccessCollection`. - subSequenceType: RandomAccessSlice.self, + subSequenceType: LazyMapRandomAccessCollection>.self, indexType: Base.Index.self, indexDistanceType: Base.IndexDistance.self, indicesType: Base.Indices.self) @@ -1167,8 +1164,7 @@ tests.test("LazyFilterCollection/AssociatedTypes") { expectCollectionAssociatedTypes( collectionType: Subject.self, iteratorType: LazyFilterIterator.self, - // FIXME(ABI)#80 (Associated Types with where clauses): SubSequence should be `LazyFilterCollection`. - subSequenceType: Slice.self, + subSequenceType: LazyFilterCollection.self, indexType: LazyFilterIndex.self, indexDistanceType: Base.IndexDistance.self, indicesType: DefaultIndices.self) @@ -1180,8 +1176,7 @@ tests.test("LazyFilterBidirectionalCollection/AssociatedTypes") { expectBidirectionalCollectionAssociatedTypes( collectionType: Subject.self, iteratorType: LazyFilterIterator.self, - // FIXME(ABI)#81 (Associated Types with where clauses): SubSequence should be `LazyFilterBidirectionalCollection`. - subSequenceType: BidirectionalSlice.self, + subSequenceType: LazyFilterBidirectionalCollection.self, indexType: LazyFilterIndex.self, indexDistanceType: Base.IndexDistance.self, indicesType: DefaultBidirectionalIndices.self) From 42968b206963ae62a1be7f7e1dcaf83c37a3bc9c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 15 Sep 2017 16:38:21 -0700 Subject: [PATCH 09/12] Eliminate a number of uses of the *Indexable protocols. --- .../CheckCollectionInstance.swift.gyb | 14 +++++++------- stdlib/public/SDK/Foundation/IndexSet.swift | 2 +- stdlib/public/core/UnsafeBufferPointer.swift.gyb | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb index f4dea7b547809..f30f439e05cec 100644 --- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb +++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb @@ -40,8 +40,8 @@ public struct CollectionMisuseResiliencyChecks { } % for inc, protocol, direction, end in ( -% ('inc', '_Indexable', 'after', 'end'), -% ('dec', '_BidirectionalIndexable', 'before', 'start')): +% ('inc', 'Collection', 'after', 'end'), +% ('dec', 'BidirectionalCollection', 'before', 'start')): /// Test that the elements of `instances` satisfy /// ${'some of ' if inc == 'dec' else ''}the semantic @@ -88,7 +88,7 @@ internal func _checkIncrementalAdvance( ${TRACE} ) where Instances : Collection, - BaseCollection : _Indexable, + BaseCollection : Collection, Instances.Iterator.Element == BaseCollection.Index { for i in instances { let d: BaseCollection.IndexDistance = sign > 0 ? @@ -122,7 +122,7 @@ public func checkForwardIndex( endIndex: Instances.Iterator.Element, ${TRACE} ) where Instances : Collection, - BaseCollection : _Indexable, + BaseCollection : Collection, Instances.Iterator.Element == BaseCollection.Index { checkIncrementable(instances, of: baseCollection, @@ -149,7 +149,7 @@ public func checkBidirectionalIndex( ${TRACE} ) where Instances: Collection, - BaseCollection : _BidirectionalIndexable, + BaseCollection : BidirectionalCollection, Instances.Iterator.Element == BaseCollection.Index { checkForwardIndex(instances, of: baseCollection, @@ -185,7 +185,7 @@ public func checkRandomAccessIndex( ) where Instances : Collection, Distances : Collection, - BaseCollection : _RandomAccessIndexable, + BaseCollection : RandomAccessCollection, Instances.Iterator.Element == BaseCollection.Index, Distances.Iterator.Element == BaseCollection.IndexDistance { @@ -214,7 +214,7 @@ public func checkAdvancesAndDistances( ) where Instances : Collection, Distances : Collection, - BaseCollection : _Indexable, + BaseCollection : Collection, Instances.Iterator.Element == BaseCollection.Index, Distances.Iterator.Element == BaseCollection.IndexDistance { diff --git a/stdlib/public/SDK/Foundation/IndexSet.swift b/stdlib/public/SDK/Foundation/IndexSet.swift index dfa5abda065b7..134119ee51ba6 100644 --- a/stdlib/public/SDK/Foundation/IndexSet.swift +++ b/stdlib/public/SDK/Foundation/IndexSet.swift @@ -371,7 +371,7 @@ public struct IndexSet : ReferenceConvertible, Equatable, BidirectionalCollectio public func intersects(integersIn range: CountableClosedRange) -> Bool { return self.intersects(integersIn: Range(range)) } // MARK: - - // Indexable + // Collection public func index(after i: Index) -> Index { if i.value + 1 == i.extent.upperBound { diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb index 8504cb3ba698b..fb947be559fdf 100644 --- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb +++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb @@ -59,7 +59,7 @@ public struct UnsafeBufferPointerIterator /// referenced memory and into the new collection. @_fixed_layout public struct Unsafe${Mutable}BufferPointer - : _${Mutable}Indexable, ${Mutable}Collection, RandomAccessCollection { + : ${Mutable}Collection, RandomAccessCollection { // FIXME: rdar://18157434 - until this is fixed, this has to be fixed layout // to avoid a hang in Foundation, which has the following setup: // struct A { struct B { let x: UnsafeMutableBufferPointer<...> } let b: B } From 797df6e8d7a3196e2e82ad757274bb0312ed564e Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 19 Sep 2017 16:09:55 -0700 Subject: [PATCH 10/12] Eliminate the _*Indexable protocols. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The various _*Indexable protocols only exist to work around the lack of recursive protocol constraints. Eliminate all of the *_Indexable protocols, collapsing their requirements into the corresponding Collection protocol (e.g., _MutableIndexable —> Collection). This introduces a number of extraneous requirements into the various Collection protocols to work around bugs in associated type inference. Specifically, to work around the lack of "global" inference of associated type witnesses. These hacks were implicitly present in the *Indexable protocols; I've made marked them as ABI FIXMEs here so we can remove them when associated type inference improves. Fixes rdar://problem/21935030 and a number of ABI FIXMEs in the library. --- stdlib/public/SDK/Dispatch/Data.swift | 1 + .../public/core/BidirectionalCollection.swift | 44 +- stdlib/public/core/Collection.swift | 377 +++++------------- stdlib/public/core/MutableCollection.swift | 149 +------ .../public/core/RandomAccessCollection.swift | 30 +- stdlib/public/core/Range.swift.gyb | 16 +- .../core/RangeReplaceableCollection.swift.gyb | 195 +-------- .../InterfaceGen/gen_swift_module.swift | 6 +- .../0089-sr4458.swift | 2 +- ...ements-llvm-function-ref-bool-swift-.swift | 2 +- ...meter-already-have-an-interface-type.swift | 2 +- .../stdlib/CollectionDiagnostics.swift | 23 +- 12 files changed, 191 insertions(+), 656 deletions(-) rename validation-test/{compiler_crashers => compiler_crashers_fixed}/28813-swift-genericsignature-enumeratepairedrequirements-llvm-function-ref-bool-swift-.swift (89%) rename validation-test/{compiler_crashers => compiler_crashers_fixed}/28835-type-hastypeparameter-already-have-an-interface-type.swift (89%) diff --git a/stdlib/public/SDK/Dispatch/Data.swift b/stdlib/public/SDK/Dispatch/Data.swift index 04922318ca734..d7ce115fe9941 100644 --- a/stdlib/public/SDK/Dispatch/Data.swift +++ b/stdlib/public/SDK/Dispatch/Data.swift @@ -299,6 +299,7 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { } public struct DispatchDataIterator : IteratorProtocol, Sequence { + public typealias Element = UInt8 /// Create an iterator over the given DispatchData public init(_data: DispatchData) { diff --git a/stdlib/public/core/BidirectionalCollection.swift b/stdlib/public/core/BidirectionalCollection.swift index 18fa13f5955f7..5abd3eb53a88d 100644 --- a/stdlib/public/core/BidirectionalCollection.swift +++ b/stdlib/public/core/BidirectionalCollection.swift @@ -17,28 +17,7 @@ /// `BidirectionalCollection` protocol instead, because it has a more complete /// interface. @available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'BidirectionalCollection' instead") -public typealias BidirectionalIndexable = _BidirectionalIndexable -public protocol _BidirectionalIndexable : _Indexable { - // FIXME(ABI)#22 (Recursive Protocol Constraints): there is no reason for this protocol - // to exist apart from missing compiler features that we emulate with it. - // rdar://problem/20531108 - // - // This protocol is almost an implementation detail of the standard - // library. - - /// Returns the position immediately before the given index. - /// - /// - Parameter i: A valid index of the collection. `i` must be greater than - /// `startIndex`. - /// - Returns: The index value immediately before `i`. - func index(before i: Index) -> Index - - /// Replaces the given index with its predecessor. - /// - /// - Parameter i: A valid index of the collection. `i` must be greater than - /// `startIndex`. - func formIndex(before i: inout Index) -} +public typealias BidirectionalIndexable = BidirectionalCollection /// A collection that supports backward as well as forward traversal. /// @@ -65,10 +44,14 @@ 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 : Collection { + // FIXME(ABI): Associated type inference requires this. + associatedtype Element + + // FIXME(ABI): Associated type inference requires this. + associatedtype Index -// TODO: swift-3-indexing-model - replaces functionality in BidirectionalIndex /// Returns the position immediately before the given index. /// /// - Parameter i: A valid index of the collection. `i` must be greater than @@ -84,7 +67,7 @@ public protocol BidirectionalCollection : _BidirectionalIndexable, Collection /// A sequence that can represent a contiguous subrange of the collection's /// elements. - associatedtype SubSequence: BidirectionalCollection + associatedtype SubSequence : BidirectionalCollection = BidirectionalSlice /// A type that represents the indices that are valid for subscripting the @@ -147,10 +130,19 @@ public protocol BidirectionalCollection : _BidirectionalIndexable, Collection /// - Parameter bounds: A range of the collection's indices. The bounds of /// the range must be valid indices of the collection. subscript(bounds: Range) -> SubSequence { get } + + // FIXME(ABI): Associated type inference requires this. + subscript(position: Index) -> Element { get } + + // FIXME(ABI): Associated type inference requires this. + var startIndex: Index { get } + + // FIXME(ABI): Associated type inference requires this. + var endIndex: Index { get } } /// Default implementation for bidirectional collections. -extension _BidirectionalIndexable { +extension BidirectionalCollection { @_inlineable // FIXME(sil-serialize-all) @inline(__always) diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift index 96b54cbd3e549..c8bdfd4895e63 100644 --- a/stdlib/public/core/Collection.swift +++ b/stdlib/public/core/Collection.swift @@ -16,143 +16,7 @@ /// In most cases, it's best to ignore this protocol and use the `Collection` /// protocol instead, because it has a more complete interface. @available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'Collection' instead") -public typealias IndexableBase = _IndexableBase -public protocol _IndexableBase { - // FIXME(ABI)#24 (Recursive Protocol Constraints): there is no reason for this protocol - // to exist apart from missing compiler features that we emulate with it. - // rdar://problem/20531108 - // - // This protocol is almost an implementation detail of the standard - // library; it is used to deduce things like the `SubSequence` and - // `Iterator` type from a minimal collection, but it is also used in - // exposed places like as a constraint on `IndexingIterator`. - - /// A type that represents a position in the collection. - /// - /// Valid indices consist of the position of every element and a - /// "past the end" position that's not valid for use as a subscript - /// argument. - associatedtype Index : Comparable - - /// The position of the first element in a nonempty collection. - /// - /// If the collection is empty, `startIndex` is equal to `endIndex`. - var startIndex: Index { get } - - /// The collection's "past the end" position---that is, the position one - /// greater than the last valid subscript argument. - /// - /// When you need a range that includes the last element of a collection, use - /// the half-open range operator (`..<`) with `endIndex`. The `..<` operator - /// creates a range that doesn't include the upper bound, so it's always - /// safe to use with `endIndex`. For example: - /// - /// let numbers = [10, 20, 30, 40, 50] - /// if let index = numbers.index(of: 30) { - /// print(numbers[index ..< numbers.endIndex]) - /// } - /// // Prints "[30, 40, 50]" - /// - /// If the collection is empty, `endIndex` is equal to `startIndex`. - var endIndex: Index { get } - - associatedtype Element - - /// Accesses the element at the specified position. - /// - /// The following example accesses an element of an array through its - /// subscript to print its value: - /// - /// var streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"] - /// print(streets[1]) - /// // Prints "Bryant" - /// - /// You can subscript a collection with any valid index other than the - /// collection's end index. The end index refers to the position one past - /// the last element of a collection, so it doesn't correspond with an - /// element. - /// - /// - Parameter position: The position of the element to access. `position` - /// must be a valid index of the collection that is not equal to the - /// `endIndex` property. - /// - /// - Complexity: O(1) - subscript(position: Index) -> Element { get } - - // WORKAROUND: rdar://25214066 - // FIXME(ABI)#178 (Type checker) - /// A sequence that represents a contiguous subrange of the collection's - /// elements. - associatedtype SubSequence - - /// Accesses the subsequence bounded by the given range. - /// - /// - Parameter bounds: A range of the collection's indices. The upper and - /// lower bounds of the range must be valid indices of the collection. - /// - /// - Complexity: O(1) - subscript(bounds: Range) -> SubSequence { get } - - /// Performs a range check in O(1), or a no-op when a range check is not - /// implementable in O(1). - /// - /// The range check, if performed, is equivalent to: - /// - /// precondition(bounds.contains(index)) - /// - /// Use this function to perform a cheap range check for QoI purposes when - /// memory safety is not a concern. Do not rely on this range check for - /// memory safety. - /// - /// The default implementation for forward and bidirectional indices is a - /// no-op. The default implementation for random access indices performs a - /// range check. - /// - /// - Complexity: O(1). - func _failEarlyRangeCheck(_ index: Index, bounds: Range) - - func _failEarlyRangeCheck(_ index: Index, bounds: ClosedRange) - - /// Performs a range check in O(1), or a no-op when a range check is not - /// implementable in O(1). - /// - /// The range check, if performed, is equivalent to: - /// - /// precondition( - /// bounds.contains(range.lowerBound) || - /// range.lowerBound == bounds.upperBound) - /// precondition( - /// bounds.contains(range.upperBound) || - /// range.upperBound == bounds.upperBound) - /// - /// Use this function to perform a cheap range check for QoI purposes when - /// memory safety is not a concern. Do not rely on this range check for - /// memory safety. - /// - /// The default implementation for forward and bidirectional indices is a - /// no-op. The default implementation for random access indices performs a - /// range check. - /// - /// - Complexity: O(1). - func _failEarlyRangeCheck(_ range: Range, bounds: Range) - - /// Returns the position immediately after the given index. - /// - /// The successor of an index must be well defined. For an index `i` into a - /// collection `c`, calling `c.index(after: i)` returns the same index every - /// time. - /// - /// - Parameter i: A valid index of the collection. `i` must be less than - /// `endIndex`. - /// - Returns: The index value immediately after `i`. - func index(after i: Index) -> Index - - /// Replaces the given index with its successor. - /// - /// - Parameter i: A valid index of the collection. `i` must be less than - /// `endIndex`. - func formIndex(after i: inout Index) -} +public typealias IndexableBase = Collection /// A type that provides subscript access to its elements, with forward index /// traversal. @@ -160,144 +24,7 @@ public protocol _IndexableBase { /// In most cases, it's best to ignore this protocol and use the `Collection` /// protocol instead, because it has a more complete interface. @available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'Collection' instead") -public typealias Indexable = _Indexable -public protocol _Indexable : _IndexableBase { - /// A type that represents the number of steps between two indices, where - /// one value is reachable from the other. - /// - /// In Swift, *reachability* refers to the ability to produce one value from - /// the other through zero or more applications of `index(after:)`. - associatedtype IndexDistance : SignedInteger = Int - - /// Returns an index that is the specified distance from the given index. - /// - /// The following example obtains an index advanced four positions from a - /// string's starting index and then prints the character at that position. - /// - /// let s = "Swift" - /// let i = s.index(s.startIndex, offsetBy: 4) - /// print(s[i]) - /// // Prints "t" - /// - /// The value passed as `n` must not offset `i` beyond the bounds of the - /// collection. - /// - /// - Parameters: - /// - i: A valid index of the collection. - /// - n: The distance to offset `i`. `n` must not be negative unless the - /// collection conforms to the `BidirectionalCollection` protocol. - /// - Returns: An index offset by `n` from the index `i`. If `n` is positive, - /// this is the same value as the result of `n` calls to `index(after:)`. - /// If `n` is negative, this is the same value as the result of `-n` calls - /// to `index(before:)`. - /// - /// - Complexity: O(1) if the collection conforms to - /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the absolute - /// value of `n`. - func index(_ i: Index, offsetBy n: IndexDistance) -> Index - - /// Returns an index that is the specified distance from the given index, - /// unless that distance is beyond a given limiting index. - /// - /// The following example obtains an index advanced four positions from a - /// string's starting index and then prints the character at that position. - /// The operation doesn't require going beyond the limiting `s.endIndex` - /// value, so it succeeds. - /// - /// let s = "Swift" - /// if let i = s.index(s.startIndex, offsetBy: 4, limitedBy: s.endIndex) { - /// print(s[i]) - /// } - /// // Prints "t" - /// - /// The next example attempts to retrieve an index six positions from - /// `s.startIndex` but fails, because that distance is beyond the index - /// passed as `limit`. - /// - /// let j = s.index(s.startIndex, offsetBy: 6, limitedBy: s.endIndex) - /// print(j) - /// // Prints "nil" - /// - /// The value passed as `n` must not offset `i` beyond the bounds of the - /// collection, unless the index passed as `limit` prevents offsetting - /// beyond those bounds. - /// - /// - Parameters: - /// - i: A valid index of the collection. - /// - n: The distance to offset `i`. `n` must not be negative unless the - /// collection conforms to the `BidirectionalCollection` protocol. - /// - limit: A valid index of the collection to use as a limit. If `n > 0`, - /// a limit that is less than `i` has no effect. Likewise, if `n < 0`, a - /// limit that is greater than `i` has no effect. - /// - Returns: An index offset by `n` from the index `i`, unless that index - /// would be beyond `limit` in the direction of movement. In that case, - /// the method returns `nil`. - /// - /// - Complexity: O(1) if the collection conforms to - /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the absolute - /// value of `n`. - func index( - _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index - ) -> Index? - - /// Offsets the given index by the specified distance. - /// - /// The value passed as `n` must not offset `i` beyond the bounds of the - /// collection. - /// - /// - Parameters: - /// - i: A valid index of the collection. - /// - n: The distance to offset `i`. `n` must not be negative unless the - /// collection conforms to the `BidirectionalCollection` protocol. - /// - /// - Complexity: O(1) if the collection conforms to - /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the absolute - /// value of `n`. - func formIndex(_ i: inout Index, offsetBy n: IndexDistance) - - /// Offsets the given index by the specified distance, or so that it equals - /// the given limiting index. - /// - /// The value passed as `n` must not offset `i` beyond the bounds of the - /// collection, unless the index passed as `limit` prevents offsetting - /// beyond those bounds. - /// - /// - Parameters: - /// - i: A valid index of the collection. - /// - n: The distance to offset `i`. `n` must not be negative unless the - /// collection conforms to the `BidirectionalCollection` protocol. - /// - limit: A valid index of the collection to use as a limit. If `n > 0`, - /// a limit that is less than `i` has no effect. Likewise, if `n < 0`, a - /// limit that is greater than `i` has no effect. - /// - Returns: `true` if `i` has been offset by exactly `n` steps without - /// going beyond `limit`; otherwise, `false`. When the return value is - /// `false`, the value of `i` is equal to `limit`. - /// - /// - Complexity: O(1) if the collection conforms to - /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the absolute - /// value of `n`. - func formIndex( - _ i: inout Index, offsetBy n: IndexDistance, limitedBy limit: Index - ) -> Bool - - /// Returns the distance between two indices. - /// - /// Unless the collection conforms to the `BidirectionalCollection` protocol, - /// `start` must be less than or equal to `end`. - /// - /// - Parameters: - /// - start: A valid index of the collection. - /// - end: Another valid index of the collection. If `end` is equal to - /// `start`, the result is zero. - /// - Returns: The distance between `start` and `end`. The result can be - /// negative only if the collection conforms to the - /// `BidirectionalCollection` protocol. - /// - /// - Complexity: O(1) if the collection conforms to - /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the - /// resulting distance. - func distance(from start: Index, to end: Index) -> IndexDistance -} +public typealias Indexable = Collection /// A type that iterates over a collection using its indices. /// @@ -618,11 +345,43 @@ public struct IndexingIterator< /// 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 : Sequence { + // FIXME(ABI): Associated type inference requires this. + associatedtype Element + + /// A type that represents a position in the collection. + /// + /// Valid indices consist of the position of every element and a + /// "past the end" position that's not valid for use as a subscript + /// argument. + associatedtype Index : Comparable + + /// The position of the first element in a nonempty collection. + /// + /// If the collection is empty, `startIndex` is equal to `endIndex`. + var startIndex: Index { get } + + /// The collection's "past the end" position---that is, the position one + /// greater than the last valid subscript argument. + /// + /// When you need a range that includes the last element of a collection, use + /// the half-open range operator (`..<`) with `endIndex`. The `..<` operator + /// creates a range that doesn't include the upper bound, so it's always + /// safe to use with `endIndex`. For example: + /// + /// let numbers = [10, 20, 30, 40, 50] + /// if let index = numbers.index(of: 30) { + /// print(numbers[index ..< numbers.endIndex]) + /// } + /// // Prints "[30, 40, 50]" + /// + /// If the collection is empty, `endIndex` is equal to `startIndex`. + var endIndex: Index { get } + /// A type that represents the number of steps between a pair of /// indices. - associatedtype IndexDistance = Int + associatedtype IndexDistance : SignedInteger = Int /// A type that provides the collection's iteration interface and /// encapsulates its iteration state. @@ -960,10 +719,70 @@ public protocol Collection : _Indexable, Sequence /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the /// resulting distance. func distance(from start: Index, to end: Index) -> IndexDistance + + /// Performs a range check in O(1), or a no-op when a range check is not + /// implementable in O(1). + /// + /// The range check, if performed, is equivalent to: + /// + /// precondition(bounds.contains(index)) + /// + /// Use this function to perform a cheap range check for QoI purposes when + /// memory safety is not a concern. Do not rely on this range check for + /// memory safety. + /// + /// The default implementation for forward and bidirectional indices is a + /// no-op. The default implementation for random access indices performs a + /// range check. + /// + /// - Complexity: O(1). + func _failEarlyRangeCheck(_ index: Index, bounds: Range) + + func _failEarlyRangeCheck(_ index: Index, bounds: ClosedRange) + + /// Performs a range check in O(1), or a no-op when a range check is not + /// implementable in O(1). + /// + /// The range check, if performed, is equivalent to: + /// + /// precondition( + /// bounds.contains(range.lowerBound) || + /// range.lowerBound == bounds.upperBound) + /// precondition( + /// bounds.contains(range.upperBound) || + /// range.upperBound == bounds.upperBound) + /// + /// Use this function to perform a cheap range check for QoI purposes when + /// memory safety is not a concern. Do not rely on this range check for + /// memory safety. + /// + /// The default implementation for forward and bidirectional indices is a + /// no-op. The default implementation for random access indices performs a + /// range check. + /// + /// - Complexity: O(1). + func _failEarlyRangeCheck(_ range: Range, bounds: Range) + + /// Returns the position immediately after the given index. + /// + /// The successor of an index must be well defined. For an index `i` into a + /// collection `c`, calling `c.index(after: i)` returns the same index every + /// time. + /// + /// - Parameter i: A valid index of the collection. `i` must be less than + /// `endIndex`. + /// - Returns: The index value immediately after `i`. + func index(after i: Index) -> Index + + /// Replaces the given index with its successor. + /// + /// - Parameter i: A valid index of the collection. `i` must be less than + /// `endIndex`. + func formIndex(after i: inout Index) } /// Default implementation for forward collections. -extension _Indexable { +extension Collection { /// Replaces the given index with its successor. /// /// - Parameter i: A valid index of the collection. `i` must be less than @@ -1881,7 +1700,7 @@ extension Collection { public typealias Generator = Iterator } -extension _IndexableBase { +extension Collection { @available(swift, deprecated: 3.2, renamed: "Element") public typealias _Element = Element } diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift index 87031e749288a..15860eccc24fc 100644 --- a/stdlib/public/core/MutableCollection.swift +++ b/stdlib/public/core/MutableCollection.swift @@ -16,139 +16,8 @@ /// `MutableCollection` protocol instead, because it has a more complete /// interface. @available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'MutableCollection' instead") -public typealias MutableIndexable = _MutableIndexable -public protocol _MutableIndexable : _Indexable { - // FIXME(ABI)#52 (Recursive Protocol Constraints): there is no reason for this protocol - // to exist apart from missing compiler features that we emulate with it. - // rdar://problem/20531108 - // - // This protocol is almost an implementation detail of the standard - // library; it is used to deduce things like the `SubSequence` and - // `Iterator` type from a minimal collection, but it is also used in - // exposed places like as a constraint on `IndexingIterator`. +public typealias MutableIndexable = MutableCollection - /// The position of the first element in a nonempty collection. - /// - /// If the collection is empty, `startIndex` is equal to `endIndex`. - var startIndex: Index { get } - - /// The collection's "past the end" position---that is, the position one - /// greater than the last valid subscript argument. - /// - /// When you need a range that includes the last element of a collection, use - /// the half-open range operator (`..<`) with `endIndex`. The `..<` operator - /// creates a range that doesn't include the upper bound, so it's always - /// safe to use with `endIndex`. For example: - /// - /// let numbers = [10, 20, 30, 40, 50] - /// if let index = numbers.index(of: 30) { - /// print(numbers[index ..< numbers.endIndex]) - /// } - /// // Prints "[30, 40, 50]" - /// - /// If the collection is empty, `endIndex` is equal to `startIndex`. - var endIndex: Index { get } - - /// Accesses the element at the specified position. - /// - /// For example, you can replace an element of an array by using its - /// subscript. - /// - /// var streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"] - /// streets[1] = "Butler" - /// print(streets[1]) - /// // Prints "Butler" - /// - /// You can subscript a collection with any valid index other than the - /// collection's end index. The end index refers to the position one - /// past the last element of a collection, so it doesn't correspond with an - /// element. - /// - /// - Parameter position: The position of the element to access. `position` - /// must be a valid index of the collection that is not equal to the - /// `endIndex` property. - subscript(position: Index) -> Element { get set } - - /// Accesses a contiguous subrange of the collection's elements. - /// - /// The accessed slice uses the same indices for the same elements as the - /// original collection. Always use the slice's `startIndex` property - /// instead of assuming that its indices start at a particular value. - /// - /// This example demonstrates getting a slice of an array of strings, finding - /// the index of one of the strings in the slice, and then using that index - /// in the original array. - /// - /// let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"] - /// let streetsSlice = streets[2 ..< streets.endIndex] - /// print(streetsSlice) - /// // Prints "["Channing", "Douglas", "Evarts"]" - /// - /// let index = streetsSlice.index(of: "Evarts") // 4 - /// streets[index!] = "Eustace" - /// print(streets[index!]) - /// // Prints "Eustace" - /// - /// - Parameter bounds: A range of the collection's indices. The bounds of - /// the range must be valid indices of the collection. - subscript(bounds: Range) -> SubSequence { get set } - - /// Performs a range check in O(1), or a no-op when a range check is not - /// implementable in O(1). - /// - /// The range check, if performed, is equivalent to: - /// - /// precondition(bounds.contains(index)) - /// - /// Use this function to perform a cheap range check for QoI purposes when - /// memory safety is not a concern. Do not rely on this range check for - /// memory safety. - /// - /// The default implementation for forward and bidirectional indices is a - /// no-op. The default implementation for random access indices performs a - /// range check. - /// - /// - Complexity: O(1). - func _failEarlyRangeCheck(_ index: Index, bounds: Range) - - /// Performs a range check in O(1), or a no-op when a range check is not - /// implementable in O(1). - /// - /// The range check, if performed, is equivalent to: - /// - /// precondition( - /// bounds.contains(range.lowerBound) || - /// range.lowerBound == bounds.upperBound) - /// precondition( - /// bounds.contains(range.upperBound) || - /// range.upperBound == bounds.upperBound) - /// - /// Use this function to perform a cheap range check for QoI purposes when - /// memory safety is not a concern. Do not rely on this range check for - /// memory safety. - /// - /// The default implementation for forward and bidirectional indices is a - /// no-op. The default implementation for random access indices performs a - /// range check. - /// - /// - Complexity: O(1). - func _failEarlyRangeCheck(_ range: Range, bounds: Range) - - /// Returns the position immediately after the given index. - /// - /// - Parameter i: A valid index of the collection. `i` must be less than - /// `endIndex`. - /// - Returns: The index value immediately after `i`. - func index(after i: Index) -> Index - - /// Replaces the given index with its successor. - /// - /// - Parameter i: A valid index of the collection. `i` must be less than - /// `endIndex`. - func formIndex(after i: inout Index) -} - -// TODO: swift-3-indexing-model - review the following /// A collection that supports subscript assignment. /// /// Collections that conform to `MutableCollection` gain the ability to @@ -196,8 +65,14 @@ public protocol _MutableIndexable : _Indexable { /// // Must be equivalent to: /// a[i] = x /// let y = x -public protocol MutableCollection : _MutableIndexable, Collection +public protocol MutableCollection : Collection { + // FIXME(ABI): Associated type inference requires this. + associatedtype Element + + // FIXME(ABI): Associated type inference requires this. + associatedtype Index + associatedtype SubSequence : MutableCollection = MutableSlice /// Accesses the element at the specified position. @@ -218,7 +93,7 @@ public protocol MutableCollection : _MutableIndexable, Collection /// - Parameter position: The position of the element to access. `position` /// must be a valid index of the collection that is not equal to the /// `endIndex` property. - subscript(position: Index) -> Element {get set} + subscript(position: Index) -> Element { get set } /// Accesses a contiguous subrange of the collection's elements. /// @@ -242,7 +117,7 @@ public protocol MutableCollection : _MutableIndexable, Collection /// /// - Parameter bounds: A range of the collection's indices. The bounds of /// the range must be valid indices of the collection. - subscript(bounds: Range) -> SubSequence {get set} + subscript(bounds: Range) -> SubSequence { get set } /// Reorders the elements of the collection such that all the elements /// that match the given predicate are after all the elements that don't @@ -306,7 +181,7 @@ public protocol MutableCollection : _MutableIndexable, Collection /// same algorithm on `body`\ 's argument lets you trade safety for /// speed. mutating func _withUnsafeMutableBufferPointerIfSupported( - _ body: (inout UnsafeMutableBufferPointer) throws -> R + _ body: (inout UnsafeMutableBufferPointer) throws -> R ) rethrows -> R? } @@ -314,7 +189,7 @@ public protocol MutableCollection : _MutableIndexable, Collection extension MutableCollection { @_inlineable public mutating func _withUnsafeMutableBufferPointerIfSupported( - _ body: (inout UnsafeMutableBufferPointer) throws -> R + _ body: (inout UnsafeMutableBufferPointer) throws -> R ) rethrows -> R? { return nil } diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift index f18dcca16df82..d3f5f3ab30736 100644 --- a/stdlib/public/core/RandomAccessCollection.swift +++ b/stdlib/public/core/RandomAccessCollection.swift @@ -16,15 +16,7 @@ /// `RandomAccessCollection` protocol instead, because it has a more complete /// interface. @available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'RandomAccessCollection' instead") -public typealias RandomAccessIndexable = _RandomAccessIndexable -public protocol _RandomAccessIndexable : _BidirectionalIndexable { - // FIXME(ABI)#54 (Recursive Protocol Constraints): there is no reason for this protocol - // to exist apart from missing compiler features that we emulate with it. - // rdar://problem/20531108 - // - // This protocol is almost an implementation detail of the standard - // library. -} +public typealias RandomAccessIndexable = RandomAccessCollection /// A collection that supports efficient random-access index traversal. /// @@ -46,9 +38,14 @@ public protocol _RandomAccessIndexable : _BidirectionalIndexable { /// collection, either the index for your custom type must conform to the /// `Strideable` protocol or you must implement the `index(_:offsetBy:)` and /// `distance(from:to:)` methods with O(1) efficiency. -public protocol RandomAccessCollection : - _RandomAccessIndexable, BidirectionalCollection +public protocol RandomAccessCollection : BidirectionalCollection { + // FIXME(ABI): Associated type inference requires this. + associatedtype Element + + // FIXME(ABI): Associated type inference requires this. + associatedtype Index + /// A collection that represents a contiguous subrange of the collection's /// elements. associatedtype SubSequence : RandomAccessCollection @@ -100,6 +97,15 @@ public protocol RandomAccessCollection : /// - Parameter bounds: A range of the collection's indices. The bounds of /// the range must be valid indices of the collection. subscript(bounds: Range) -> SubSequence { get } + + // FIXME(ABI): Associated type inference requires this. + subscript(position: Index) -> Element { get } + + // FIXME(ABI): Associated type inference requires this. + var startIndex: Index { get } + + // FIXME(ABI): Associated type inference requires this. + var endIndex: Index { get } } /// Supply the default "slicing" `subscript` for `RandomAccessCollection` @@ -143,7 +149,7 @@ extension RandomAccessCollection where SubSequence == RandomAccessSlice { // wrong complexity. /// Default implementation for random access collections. -extension _RandomAccessIndexable { +extension RandomAccessCollection { /// Returns an index that is the specified distance from the given index, /// unless that distance is beyond a given limiting index. /// diff --git a/stdlib/public/core/Range.swift.gyb b/stdlib/public/core/Range.swift.gyb index f21e15ab8f72c..d0066b7901cba 100644 --- a/stdlib/public/core/Range.swift.gyb +++ b/stdlib/public/core/Range.swift.gyb @@ -60,7 +60,7 @@ public protocol RangeExpression { /// is *not* guaranteed to be inside the bounds of `collection`. Callers /// should apply the same preconditions to the return value as they would /// to a range provided directly by the user. - func relative( + func relative( to collection: C ) -> Range where C.Index == Bound @@ -590,7 +590,7 @@ extension ${Self} { extension ${Self}: RangeExpression { @_inlineable // FIXME(sil-serialize-all) - public func relative(to collection: C) -> Range + public func relative(to collection: C) -> Range where C.Index == Bound { % if 'Closed' in Self: return Range( @@ -821,7 +821,7 @@ public struct PartialRangeUpTo: RangeExpression { @_inlineable // FIXME(sil-serialize-all) @_transparent - public func relative(to collection: C) -> Range + public func relative(to collection: C) -> Range where C.Index == Bound { return collection.startIndex..: RangeExpression { @_inlineable // FIXME(sil-serialize-all) @_transparent - public func relative(to collection: C) -> Range + public func relative(to collection: C) -> Range where C.Index == Bound { return collection.startIndex..: RangeExpression { @_inlineable // FIXME(sil-serialize-all) @_transparent - public func relative(to collection: C) -> Range + public func relative(to collection: C) -> Range where C.Index == Bound { return self.lowerBound..( + public func relative( to collection: C ) -> Range where C.Index == Bound { return self.lowerBound..() -extension _Indexable { +extension Collection { @_inlineable public subscript(r: R) -> SubSequence where R.Bound == Index { @@ -1226,7 +1226,7 @@ extension _Indexable { return self[startIndex...] } } -extension _MutableIndexable { +extension MutableCollection { @_inlineable public subscript(r: R) -> SubSequence where R.Bound == Index { diff --git a/stdlib/public/core/RangeReplaceableCollection.swift.gyb b/stdlib/public/core/RangeReplaceableCollection.swift.gyb index 53d99403f8a2a..eda9d20187bdd 100644 --- a/stdlib/public/core/RangeReplaceableCollection.swift.gyb +++ b/stdlib/public/core/RangeReplaceableCollection.swift.gyb @@ -14,8 +14,6 @@ // //===----------------------------------------------------------------------===// -// FIXME: swift-3-indexing-model: synchronize _Indexable with the actual -// protocol. /// A type that supports replacement of an arbitrary subrange of elements with /// the elements of another collection. /// @@ -23,176 +21,7 @@ /// `RangeReplaceableCollection` protocol instead, because it has a more /// complete interface. @available(*, deprecated, message: "it will be removed in Swift 4.0. Please use 'RandomAccessCollection' instead") -public typealias RangeReplaceableIndexable = _RangeReplaceableIndexable -public protocol _RangeReplaceableIndexable : _Indexable { - // FIXME(ABI)#58 (Recursive Protocol Constraints): there is no reason for this protocol - // to exist apart from missing compiler features that we emulate with it. - // rdar://problem/20531108 - // - // This protocol is almost an implementation detail of the standard - // library. - - /// Creates an empty instance. - init() - - /// Creates a new collection containing the specified number of a single, - /// repeated value. - /// - /// Here's an example of creating an array initialized with five strings - /// containing the letter *Z*. - /// - /// let fiveZs = Array(repeating: "Z", count: 5) - /// print(fiveZs) - /// // Prints "["Z", "Z", "Z", "Z", "Z"]" - /// - /// - Parameters: - /// - repeatedValue: The element to repeat. - /// - count: The number of times to repeat the value passed in the - /// `repeating` parameter. `count` must be zero or greater. - init(repeating repeatedValue: Element, count: Int) - - /// Creates a new instance of a collection containing the elements of a - /// sequence. - /// - /// - Parameter elements: The sequence of elements for the new collection. - /// `elements` must be finite. - init(_ elements: S) where S.Element == Element - - /// Replaces the specified subrange of elements with the given collection. - /// - /// This method has the effect of removing the specified range of elements - /// from the collection and inserting the new elements at the same location. - /// The number of new elements need not match the number of elements being - /// removed. - /// - /// In this example, three elements in the middle of an array of integers are - /// replaced by the five elements of a `Repeated` instance. - /// - /// var nums = [10, 20, 30, 40, 50] - /// nums.replaceSubrange(1...3, with: repeatElement(1, count: 5)) - /// print(nums) - /// // Prints "[10, 1, 1, 1, 1, 1, 50]" - /// - /// If you pass a zero-length range as the `subrange` parameter, this method - /// inserts the elements of `newElements` at `subrange.startIndex`. Calling - /// the `insert(contentsOf:at:)` method instead is preferred. - /// - /// Likewise, if you pass a zero-length collection as the `newElements` - /// parameter, this method removes the elements in the given subrange - /// without replacement. Calling the `removeSubrange(_:)` method instead is - /// preferred. - /// - /// Calling this method may invalidate any existing indices for use with this - /// collection. - /// - /// - Parameters: - /// - subrange: The subrange of the collection to replace. The bounds of - /// the range must be valid indices of the collection. - /// - newElements: The new elements to add to the collection. - /// - /// - Complexity: O(*m*), where *m* is the combined length of the collection - /// and `newElements`. If the call to `replaceSubrange` simply appends the - /// contents of `newElements` to the collection, the complexity is O(*n*), - /// where *n* is the length of `newElements`. - mutating func replaceSubrange( - _ subrange: Range, - with newElements: C - ) where C : Collection, C.Element == Element - - /// Inserts a new element into the collection at the specified position. - /// - /// The new element is inserted before the element currently at the specified - /// index. If you pass the collection's `endIndex` property as the `index` - /// parameter, the new element is appended to the collection. - /// - /// var numbers = [1, 2, 3, 4, 5] - /// numbers.insert(100, at: 3) - /// numbers.insert(200, at: numbers.endIndex) - /// - /// print(numbers) - /// // Prints "[1, 2, 3, 100, 4, 5, 200]" - /// - /// Calling this method may invalidate any existing indices for use with this - /// collection. - /// - /// - Parameters: - /// - newElement: The new element to insert into the collection. - /// - i: The position at which to insert the new element. `index` must be a - /// valid index into the collection. - /// - /// - Complexity: O(*n*), where *n* is the length of the collection. - mutating func insert(_ newElement: Element, at i: Index) - - /// Inserts the elements of a sequence into the collection at the specified - /// position. - /// - /// The new elements are inserted before the element currently at the - /// specified index. If you pass the collection's `endIndex` property as the - /// `index` parameter, the new elements are appended to the collection. - /// - /// Here's an example of inserting a range of integers into an array of the - /// same type: - /// - /// var numbers = [1, 2, 3, 4, 5] - /// numbers.insert(contentsOf: 100...103, at: 3) - /// print(numbers) - /// // Prints "[1, 2, 3, 100, 101, 102, 103, 4, 5]" - /// - /// Calling this method may invalidate any existing indices for use with this - /// collection. - /// - /// - Parameters: - /// - newElements: The new elements to insert into the collection. - /// - i: The position at which to insert the new elements. `index` must be - /// a valid index of the collection. - /// - /// - Complexity: O(*m*), where *m* is the combined length of the collection - /// and `newElements`. If `i` is equal to the collection's `endIndex` - /// property, the complexity is O(*n*), where *n* is the length of - /// `newElements`. - mutating func insert( - contentsOf newElements: S, at i: Index - ) where S.Element == Element - - /// Removes and returns the element at the specified position. - /// - /// All the elements following the specified position are moved to close the - /// gap. This example removes the middle element from an array of - /// measurements. - /// - /// var measurements = [1.2, 1.5, 2.9, 1.2, 1.6] - /// let removed = measurements.remove(at: 2) - /// print(measurements) - /// // Prints "[1.2, 1.5, 1.2, 1.6]" - /// - /// Calling this method may invalidate any existing indices for use with this - /// collection. - /// - /// - Parameter i: The position of the element to remove. `index` must be - /// a valid index of the collection that is not equal to the collection's - /// end index. - /// - Returns: The removed element. - /// - /// - Complexity: O(*n*), where *n* is the length of the collection. - @discardableResult - mutating func remove(at i: Index) -> Element - - /// Removes the specified subrange of elements from the collection. - /// - /// var bugs = ["Aphid", "Bumblebee", "Cicada", "Damselfly", "Earwig"] - /// bugs.removeSubrange(1...3) - /// print(bugs) - /// // Prints "["Aphid", "Earwig"]" - /// - /// Calling this method may invalidate any existing indices for use with this - /// collection. - /// - /// - Parameter bounds: The subrange of the collection to remove. The bounds - /// of the range must be valid indices of the collection. - /// - /// - Complexity: O(*n*), where *n* is the length of the collection. - mutating func removeSubrange(_ bounds: Range) -} +public typealias RangeReplaceableIndexable = RangeReplaceableCollection /// A collection that supports replacement of an arbitrary subrange of elements /// with the elements of another collection. @@ -241,8 +70,7 @@ public protocol _RangeReplaceableIndexable : _Indexable { /// `replaceSubrange(_:with:)` with an empty collection for the `newElements` /// parameter. You can override any of the protocol's required methods to /// provide your own custom implementation. -public protocol RangeReplaceableCollection - : _RangeReplaceableIndexable, Collection +public protocol RangeReplaceableCollection : Collection { associatedtype SubSequence : RangeReplaceableCollection = RangeReplaceableSlice @@ -448,6 +276,22 @@ public protocol RangeReplaceableCollection @discardableResult mutating func remove(at i: Index) -> Element + /// Removes the specified subrange of elements from the collection. + /// + /// var bugs = ["Aphid", "Bumblebee", "Cicada", "Damselfly", "Earwig"] + /// bugs.removeSubrange(1...3) + /// print(bugs) + /// // Prints "["Aphid", "Earwig"]" + /// + /// Calling this method may invalidate any existing indices for use with this + /// collection. + /// + /// - Parameter bounds: The subrange of the collection to remove. The bounds + /// of the range must be valid indices of the collection. + /// + /// - Complexity: O(*n*), where *n* is the length of the collection. + mutating func removeSubrange(_ bounds: Range) + /// Customization point for `removeLast()`. Implement this function if you /// want to replace the default implementation. /// @@ -508,6 +352,9 @@ public protocol RangeReplaceableCollection /// /// - Complexity: O(*n*), where *n* is the length of the collection. mutating func removeAll(keepingCapacity keepCapacity: Bool /*= false*/) + + // FIXME(ABI): Associated type inference requires this. + subscript(bounds: Range) -> SubSequence { get } } //===----------------------------------------------------------------------===// diff --git a/test/SourceKit/InterfaceGen/gen_swift_module.swift b/test/SourceKit/InterfaceGen/gen_swift_module.swift index 33c441896d70d..7df6ce9408994 100644 --- a/test/SourceKit/InterfaceGen/gen_swift_module.swift +++ b/test/SourceKit/InterfaceGen/gen_swift_module.swift @@ -15,12 +15,12 @@ func f(s : inout [Int]) { // RUN: %swift -emit-module -o %t.mod/swift_mod_syn.swiftmodule %S/Inputs/swift_mod_syn.swift -parse-as-library // RUN: %sourcekitd-test -req=interface-gen-open -module swift_mod_syn -- -I %t.mod == -req=cursor -pos=4:7 %s -- %s -I %t.mod | %FileCheck -check-prefix=SYNTHESIZED-USR1 %s -// SYNTHESIZED-USR1: s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements8SequencePRpzlE4sortyyF::SYNTHESIZED::s:Sa +// SYNTHESIZED-USR1: s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements013BidirectionalB0PRpzlE4sortyyF::SYNTHESIZED::s:Sa // RUN: %sourcekitd-test -req=interface-gen-open -module Swift -synthesized-extension \ -// RUN: == -req=find-usr -usr "s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements8SequencePRpzlE4sortyyF::SYNTHESIZED::s:Sa" | %FileCheck -check-prefix=SYNTHESIZED-USR2 %s +// RUN: == -req=find-usr -usr "s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements013BidirectionalB0PRpzlE4sortyyF::SYNTHESIZED::s:Sa" | %FileCheck -check-prefix=SYNTHESIZED-USR2 %s // SYNTHESIZED-USR2-NOT: USR NOT FOUND // RUN: %sourcekitd-test -req=interface-gen-open -module Swift \ -// RUN: == -req=find-usr -usr "s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements8SequencePRpzlE4sortyyF::SYNTHESIZED::s:Sa::SYNTHESIZED::USRDOESNOTEXIST" | %FileCheck -check-prefix=SYNTHESIZED-USR3 %s +// RUN: == -req=find-usr -usr "s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements013BidirectionalB0PRpzlE4sortyyF::SYNTHESIZED::s:Sa::SYNTHESIZED::USRDOESNOTEXIST" | %FileCheck -check-prefix=SYNTHESIZED-USR3 %s // SYNTHESIZED-USR3-NOT: USR NOT FOUND diff --git a/validation-test/compiler_crashers_2_fixed/0089-sr4458.swift b/validation-test/compiler_crashers_2_fixed/0089-sr4458.swift index 25e0ec7f55252..86d9c05951bca 100644 --- a/validation-test/compiler_crashers_2_fixed/0089-sr4458.swift +++ b/validation-test/compiler_crashers_2_fixed/0089-sr4458.swift @@ -4,7 +4,7 @@ import Foundation -extension _MutableIndexable { +extension MutableCollection { typealias SubSequence = MutableRangeReplaceableRandomAccessSlice } diff --git a/validation-test/compiler_crashers/28813-swift-genericsignature-enumeratepairedrequirements-llvm-function-ref-bool-swift-.swift b/validation-test/compiler_crashers_fixed/28813-swift-genericsignature-enumeratepairedrequirements-llvm-function-ref-bool-swift-.swift similarity index 89% rename from validation-test/compiler_crashers/28813-swift-genericsignature-enumeratepairedrequirements-llvm-function-ref-bool-swift-.swift rename to validation-test/compiler_crashers_fixed/28813-swift-genericsignature-enumeratepairedrequirements-llvm-function-ref-bool-swift-.swift index cfa8ae63bd22b..b17f98501c32a 100644 --- a/validation-test/compiler_crashers/28813-swift-genericsignature-enumeratepairedrequirements-llvm-function-ref-bool-swift-.swift +++ b/validation-test/compiler_crashers_fixed/28813-swift-genericsignature-enumeratepairedrequirements-llvm-function-ref-bool-swift-.swift @@ -5,5 +5,5 @@ // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// RUN: not --crash %target-swift-frontend %s -emit-ir +// RUN: not %target-swift-frontend %s -emit-ir protocol A:Collection}extension CountableRange{protocol P{protocol P{struct a:A{}typealias a:A}{}typealias e:P diff --git a/validation-test/compiler_crashers/28835-type-hastypeparameter-already-have-an-interface-type.swift b/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift similarity index 89% rename from validation-test/compiler_crashers/28835-type-hastypeparameter-already-have-an-interface-type.swift rename to validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift index 44b25ed584709..f0dbe14336609 100644 --- a/validation-test/compiler_crashers/28835-type-hastypeparameter-already-have-an-interface-type.swift +++ b/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift @@ -6,7 +6,7 @@ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // REQUIRES: asserts -// RUN: not --crash %target-swift-frontend %s -emit-ir +// RUN: not %target-swift-frontend %s -emit-ir class a @@ -59,30 +57,27 @@ struct GoodIndexable : Indexable { var endIndex: Int { return 0 } subscript(pos: Int) -> Int { return 0 } - subscript(bounds: Range) -> [Int] { return [] } + subscript(bounds: Range) -> ArraySlice { return [] } } -// expected-warning@+2 {{'Indexable' is deprecated: it will be removed in Swift 4.0. Please use 'Collection' instead}} -// expected-error@+1 {{type 'BadIndexable1' does not conform to protocol '_IndexableBase'}} -struct BadIndexable1 : Indexable { +// expected-warning@+1 {{'Indexable' is deprecated: it will be removed in Swift 4.0. Please use 'Collection' instead}} +struct AnotherGoodIndexable1 : Indexable { func index(after i: Int) -> Int { return i + 1 } var startIndex: Int { return 0 } var endIndex: Int { return 0 } subscript(pos: Int) -> Int { return 0 } - - // Missing 'subscript(_:) -> SubSequence'. } // expected-warning@+2 {{'Indexable' is deprecated: it will be removed in Swift 4.0. Please use 'Collection' instead}} -// expected-error@+1 {{type 'BadIndexable2' does not conform to protocol '_IndexableBase'}} +// expected-error@+1 {{type 'BadIndexable2' does not conform to protocol 'Collection'}} struct BadIndexable2 : Indexable { var startIndex: Int { return 0 } var endIndex: Int { return 0 } subscript(pos: Int) -> Int { return 0 } - subscript(bounds: Range) -> [Int] { return [] } + subscript(bounds: Range) -> ArraySlice { return [] } // Missing index(after:) -> Int } @@ -94,7 +89,7 @@ struct GoodBidirectionalIndexable1 : BidirectionalIndexable { func index(before i: Int) -> Int { return i - 1 } subscript(pos: Int) -> Int { return 0 } - subscript(bounds: Range) -> [Int] { return [] } + subscript(bounds: Range) -> ArraySlice { return [] } } // We'd like to see: {{type 'BadBidirectionalIndexable' does not conform to protocol 'BidirectionalIndexable'}} @@ -105,12 +100,12 @@ struct BadBidirectionalIndexable : BidirectionalIndexable { var endIndex: Int { return 0 } subscript(pos: Int) -> Int { return 0 } - subscript(bounds: Range) -> [Int] { return [] } + subscript(bounds: Range) -> ArraySlice { return [] } // This is a poor error message; it would be better to get a message // that index(before:) was missing. // - // expected-error@+1 {{'index(after:)' has different argument labels from those required by protocol '_BidirectionalIndexable' ('index(before:)'}} + // expected-error@+1 {{'index(after:)' has different argument labels from those required by protocol 'BidirectionalCollection' ('index(before:)'}} func index(after i: Int) -> Int { return 0 } } From 772352e5247c17c19fcbdd9385a426ba9e07113c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 22 Sep 2017 12:35:35 -0700 Subject: [PATCH 11/12] Add requirement StringProtocol.SubSequence : StringProtocol --- stdlib/public/core/String.swift | 2 +- test/stdlib/StringCompatibility.swift | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift index 3094471a58d89..85dce6284bf67 100644 --- a/stdlib/public/core/String.swift +++ b/stdlib/public/core/String.swift @@ -21,7 +21,7 @@ public protocol StringProtocol TextOutputStream, TextOutputStreamable, LosslessStringConvertible, ExpressibleByStringLiteral, Hashable, Comparable - where Iterator.Element == Character { + where Iterator.Element == Character, SubSequence : StringProtocol { associatedtype UTF8View : /*Bidirectional*/Collection where UTF8View.Element == UInt8 // Unicode.UTF8.CodeUnit diff --git a/test/stdlib/StringCompatibility.swift b/test/stdlib/StringCompatibility.swift index 9780d215f4154..b4ee7933e7198 100644 --- a/test/stdlib/StringCompatibility.swift +++ b/test/stdlib/StringCompatibility.swift @@ -18,10 +18,14 @@ extension MyString : BidirectionalCollection { typealias Iterator = String.Iterator typealias Index = String.Index typealias IndexDistance = String.IndexDistance + typealias SubSequence = MyString func makeIterator() -> Iterator { return base.makeIterator() } var startIndex: String.Index { return base.startIndex } var endIndex: String.Index { return base.startIndex } subscript(i: Index) -> Character { return base[i] } + subscript(indices: Range) -> MyString { + return MyString(base: String(self.base[indices])) + } func index(after i: Index) -> Index { return base.index(after: i) } func index(before i: Index) -> Index { return base.index(before: i) } func index(_ i: Index, offsetBy n: IndexDistance) -> Index { From 5db9b11f2f5bdd87ecb658a2887e772e54411c8b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sun, 1 Oct 2017 20:18:24 -0700 Subject: [PATCH 12/12] Address a resolved crasher --- .../28796-result-second.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename validation-test/{compiler_crashers => compiler_crashers_fixed}/28796-result-second.swift (89%) diff --git a/validation-test/compiler_crashers/28796-result-second.swift b/validation-test/compiler_crashers_fixed/28796-result-second.swift similarity index 89% rename from validation-test/compiler_crashers/28796-result-second.swift rename to validation-test/compiler_crashers_fixed/28796-result-second.swift index 581543953baea..316ac8c00aa00 100644 --- a/validation-test/compiler_crashers/28796-result-second.swift +++ b/validation-test/compiler_crashers_fixed/28796-result-second.swift @@ -6,5 +6,5 @@ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // REQUIRES: asserts -// RUN: not --crash %target-swift-frontend %s -emit-ir +// RUN: not %target-swift-frontend %s -emit-ir class a