Skip to content

[stdlib] Adopt conditional conformance for Indices, Slice, ReversedCollection #12913

New issue

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

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

Already on GitHub? Sign in to your account

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ self.test("\(testNamePrefix).subscript(_: Range)/Set/semantics") {
// Call setter implicitly through an inout mutation.
var c = makeWrappedCollection(test.collection)

_mapInPlace(&c[test.bounds(in: c)]) {
var s = c[test.bounds(in: c)]
_mapInPlace(&s) {
wrapValue(OpaqueValue(extractValue($0).value + 90000))
}

Expand Down
31 changes: 8 additions & 23 deletions stdlib/public/core/BidirectionalCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,20 @@ public typealias BidirectionalIndexable = BidirectionalCollection
/// `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 : Collection
{
public protocol BidirectionalCollection: Collection
where SubSequence: BidirectionalCollection, Indices: BidirectionalCollection {
// FIXME(ABI): Associated type inference requires this.
associatedtype Element

// FIXME(ABI): Associated type inference requires this.
associatedtype Index

// FIXME(ABI): Associated type inference requires this.
associatedtype SubSequence = Slice<Self>

// FIXME(ABI): Associated type inference requires this.
associatedtype Indices = DefaultIndices<Self>

/// Returns the position immediately before the given index.
///
/// - Parameter i: A valid index of the collection. `i` must be greater than
Expand All @@ -65,16 +71,6 @@ public protocol BidirectionalCollection : Collection
/// `startIndex`.
func formIndex(before i: inout Index)

/// A sequence that can represent a contiguous subrange of the collection's
/// elements.
associatedtype SubSequence : BidirectionalCollection
= BidirectionalSlice<Self>

/// A type that represents the indices that are valid for subscripting the
/// collection, in ascending order.
associatedtype Indices : BidirectionalCollection
= DefaultBidirectionalIndices<Self>

/// The indices that are valid for subscripting the collection, in ascending
/// order.
///
Expand Down Expand Up @@ -201,17 +197,6 @@ extension BidirectionalCollection {
}
}

/// Supply the default "slicing" `subscript` for `BidirectionalCollection`
/// models that accept the default associated `SubSequence`,
/// `BidirectionalSlice<Self>`.
extension BidirectionalCollection where SubSequence == BidirectionalSlice<Self> {
@_inlineable // FIXME(sil-serialize-all)
public subscript(bounds: Range<Index>) -> BidirectionalSlice<Self> {
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
return BidirectionalSlice(base: self, bounds: bounds)
}
}

extension BidirectionalCollection where SubSequence == Self {
/// Removes and returns the last element of the collection.
///
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ set(SWIFTLIB_ESSENTIAL
HeapBuffer.swift
ICU.swift
ImplicitlyUnwrappedOptional.swift
Indices.swift.gyb
Indices.swift
InputStream.swift
IntegerParsing.swift
Integers.swift.gyb
Expand Down Expand Up @@ -100,7 +100,7 @@ set(SWIFTLIB_ESSENTIAL
Print.swift
RandomAccessCollection.swift
Range.swift.gyb
RangeReplaceableCollection.swift.gyb
RangeReplaceableCollection.swift
ReflectionLegacy.swift
Repeat.swift
REPL.swift
Expand All @@ -115,7 +115,7 @@ set(SWIFTLIB_ESSENTIAL
SetAlgebra.swift
ShadowProtocols.swift
Shims.swift
Slice.swift.gyb
Slice.swift
Sort.swift.gyb
StaticString.swift
Stride.swift.gyb
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/ClosedRange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ public struct CountableClosedRange<Bound> : RandomAccessCollection

@_inlineable
public subscript(bounds: Range<Index>)
-> RandomAccessSlice<CountableClosedRange<Bound>> {
return RandomAccessSlice(base: self, bounds: bounds)
-> Slice<CountableClosedRange<Bound>> {
return Slice(base: self, bounds: bounds)
}

/// Creates an instance with the given bounds.
Expand Down
24 changes: 13 additions & 11 deletions stdlib/public/core/Collection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,11 @@ public typealias Indexable = Collection
/// // Prints "15.0"
/// // Prints "20.0"
@_fixed_layout
public struct IndexingIterator<
Elements : Collection
> : IteratorProtocol, Sequence {
public struct IndexingIterator<Elements : Collection> {
@_versioned
internal let _elements: Elements
@_versioned
internal var _position: Elements.Index

@_inlineable
@inline(__always)
Expand All @@ -103,6 +105,12 @@ public struct IndexingIterator<
self._elements = _elements
self._position = _position
}
}

extension IndexingIterator: IteratorProtocol, Sequence {
public typealias Element = Elements.Element
public typealias Iterator = IndexingIterator<Elements>
public typealias SubSequence = AnySequence<Element>

/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
Expand Down Expand Up @@ -136,11 +144,6 @@ public struct IndexingIterator<
_elements.formIndex(after: &_position)
return element
}

@_versioned
internal let _elements: Elements
@_versioned
internal var _position: Elements.Index
}

/// A sequence whose elements can be traversed multiple times,
Expand Down Expand Up @@ -345,8 +348,7 @@ 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 : Sequence
{
public protocol Collection: Sequence where SubSequence: Collection {
// FIXME(ABI): Associated type inference requires this.
associatedtype Element

Expand Down Expand Up @@ -403,7 +405,7 @@ public protocol Collection : 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 : Collection = Slice<Self>
associatedtype SubSequence = Slice<Self>
where SubSequence.Index == Index,
SubSequence.IndexDistance == IndexDistance

Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/CollectionOfOne.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ public struct CollectionOfOne<Element>

@_inlineable // FIXME(sil-serialize-all)
public subscript(bounds: Range<Int>)
-> MutableRandomAccessSlice<CollectionOfOne<Element>> {
-> Slice<CollectionOfOne<Element>> {
get {
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
return MutableRandomAccessSlice(base: self, bounds: bounds)
return Slice(base: self, bounds: bounds)
}
set {
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/Flatten.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,8 @@ public struct ${Collection}<Base> : ${collectionForTraversal(traversal)}

@_inlineable // FIXME(sil-serialize-all)
public subscript(bounds: Range<Index>)
-> ${Slice}<${Collection}> {
return ${Slice}(base: self, bounds: bounds)
-> Slice<${Collection}> {
return Slice(base: self, bounds: bounds)
}

// To return any estimate of the number of elements, we have to start
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,15 @@
//
//===----------------------------------------------------------------------===//

%{
from gyb_stdlib_support import (
TRAVERSALS,
collectionForTraversal,
defaultIndicesForTraversal,
documentationNameForTraversal
)
}%

% for Traversal in TRAVERSALS:
% Self = defaultIndicesForTraversal(Traversal)
% collection = documentationNameForTraversal(Traversal)

// FIXME(ABI)#42 (Conditional Conformance): There should be just one default
// indices type that has conditional conformances to
// `BidirectionalCollection` and `RandomAccessCollection`.
// <rdar://problem/17144340>

/// A collection of indices for an arbitrary ${collection}.
/// A collection of indices for an arbitrary collection
@_fixed_layout
public struct ${Self}<
Elements : ${collectionForTraversal(Traversal)}
> : ${collectionForTraversal(Traversal)} {

public typealias Index = Elements.Index
public typealias Indices = ${Self}<Elements>
public struct DefaultIndices<Elements: Collection> {
@_versioned
internal var _elements: Elements
@_versioned
internal var _startIndex: Elements.Index
@_versioned
internal var _endIndex: Elements.Index

@_inlineable
@_versioned
Expand All @@ -48,6 +31,16 @@ public struct ${Self}<
self._startIndex = startIndex
self._endIndex = endIndex
}
}

extension DefaultIndices: Collection {

public typealias Index = Elements.Index
public typealias Element = Elements.Index
public typealias Indices = DefaultIndices<Elements>
public typealias SubSequence = DefaultIndices<Elements>
public typealias IndexDistance = Elements.IndexDistance
public typealias Iterator = IndexingIterator<DefaultIndices<Elements>>

@_inlineable
public var startIndex: Index {
Expand All @@ -65,12 +58,10 @@ public struct ${Self}<
return i
}

public typealias SubSequence = ${Self}<Elements>

@_inlineable
public subscript(bounds: Range<Index>) -> ${Self}<Elements> {
public subscript(bounds: Range<Index>) -> DefaultIndices<Elements> {
// FIXME: swift-3-indexing-model: range check.
return ${Self}(
return DefaultIndices(
_elements: _elements,
startIndex: bounds.lowerBound,
endIndex: bounds.upperBound)
Expand All @@ -88,7 +79,14 @@ public struct ${Self}<
_elements.formIndex(after: &i)
}

% if Traversal in ['Bidirectional', 'RandomAccess']:
@_inlineable
public var indices: Indices {
return self
}
}

extension DefaultIndices: BidirectionalCollection
where Elements: BidirectionalCollection {
@_inlineable
public func index(before i: Index) -> Index {
// FIXME: swift-3-indexing-model: range check.
Expand All @@ -100,23 +98,12 @@ public struct ${Self}<
// FIXME: swift-3-indexing-model: range check.
_elements.formIndex(before: &i)
}
% end

@_inlineable
public var indices: Indices {
return self
}

@_versioned
internal var _elements: Elements
@_versioned
internal var _startIndex: Elements.Index
@_versioned
internal var _endIndex: Elements.Index
}

extension ${collectionForTraversal(Traversal)}
where Indices == ${Self}<Self> {
extension DefaultIndices: RandomAccessCollection
where Elements: RandomAccessCollection { }

extension Collection where Indices == DefaultIndices<Self> {
/// The indices that are valid for subscripting the collection, in ascending
/// order.
///
Expand All @@ -135,16 +122,13 @@ where Indices == ${Self}<Self> {
/// }
/// // c == MyFancyCollection([2, 4, 6, 8, 10])
@_inlineable // FIXME(sil-serialize-all)
public var indices: ${Self}<Self> {
return ${Self}(
public var indices: DefaultIndices<Self> {
return DefaultIndices(
_elements: self,
startIndex: self.startIndex,
endIndex: self.endIndex)
}
}

% end

// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:
public typealias DefaultBidirectionalIndices<T: BidirectionalCollection> = DefaultIndices<T>
public typealias DefaultRandomAccessIndices<T: RandomAccessCollection> = DefaultIndices<T>
2 changes: 1 addition & 1 deletion stdlib/public/core/Integers.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -3208,7 +3208,7 @@ ${assignmentOperatorComment(x.operator, True)}
@_fixed_layout // FIXME(sil-serialize-all)
public struct Words : BidirectionalCollection {
public typealias Indices = CountableRange<Int>
public typealias SubSequence = BidirectionalSlice<${Self}.Words>
public typealias SubSequence = Slice<${Self}.Words>

@_versioned // FIXME(sil-serialize-all)
internal var _value: ${Self}
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/LazyCollection.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ extension ${Self} : ${TraversalCollection} {
///
/// - Complexity: O(1)
@_inlineable
public subscript(bounds: Range<Index>) -> ${Slice}<${Self}<Base>> {
return ${Slice}(base: self, bounds: bounds)
public subscript(bounds: Range<Index>) -> Slice<${Self}<Base>> {
return Slice(base: self, bounds: bounds)
}

/// A Boolean value indicating whether the collection is empty.
Expand Down
Loading