Skip to content

[stdlib] Constrain BinaryInteger.Words to be a Collection #11178

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

Closed
wants to merge 5 commits into from
Closed
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
62 changes: 31 additions & 31 deletions stdlib/public/core/Collection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,37 @@ public protocol _Indexable : _IndexableBase {
/// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the
/// resulting distance.
func distance(from start: Index, to end: Index) -> IndexDistance

/// A Boolean value indicating whether the collection is empty.
///
/// When you need to check whether your collection is empty, use the
/// `isEmpty` property instead of checking that the `count` property is
/// equal to zero. For collections that don't conform to
/// `RandomAccessCollection`, accessing the `count` property iterates
/// through the elements of the collection.
///
/// let horseName = "Silver"
/// if horseName.isEmpty {
/// print("I've been through the desert on a horse with no name.")
/// } else {
/// print("Hi ho, \(horseName)!")
/// }
/// // Prints "Hi ho, Silver!")
///
/// - Complexity: O(1)
var isEmpty: Bool { get }

/// The number of elements in the collection.
///
/// To check whether a collection is empty, use its `isEmpty` property
/// instead of comparing `count` to zero. Unless the collection guarantees
/// random-access performance, calculating `count` can be an O(*n*)
/// operation.
///
/// - Complexity: O(1) if the collection conforms to
/// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the length
/// of the collection.
var count: IndexDistance { get }
}

/// A type that iterates over a collection using its indices.
Expand Down Expand Up @@ -853,37 +884,6 @@ public protocol Collection : _Indexable, Sequence
/// - Complexity: O(1)
func prefix(through position: Index) -> SubSequence

/// A Boolean value indicating whether the collection is empty.
///
/// When you need to check whether your collection is empty, use the
/// `isEmpty` property instead of checking that the `count` property is
/// equal to zero. For collections that don't conform to
/// `RandomAccessCollection`, accessing the `count` property iterates
/// through the elements of the collection.
///
/// let horseName = "Silver"
/// if horseName.isEmpty {
/// print("I've been through the desert on a horse with no name.")
/// } else {
/// print("Hi ho, \(horseName)!")
/// }
/// // Prints "Hi ho, Silver!")
///
/// - Complexity: O(1)
var isEmpty: Bool { get }

/// The number of elements in the collection.
///
/// To check whether a collection is empty, use its `isEmpty` property
/// instead of comparing `count` to zero. Unless the collection guarantees
/// random-access performance, calculating `count` can be an O(*n*)
/// operation.
///
/// - Complexity: O(1) if the collection conforms to
/// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the length
/// of the collection.
var count: IndexDistance { get }

// The following requirement enables dispatching for index(of:) when
// the element type is Equatable.
/// Returns `Optional(Optional(index))` if an element was found
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/core/DoubleWidth.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@

/// A fixed-width integer that is twice the size of its base type.
public struct DoubleWidth<Base : FixedWidthInteger> :
FixedWidthInteger, _ExpressibleByBuiltinIntegerLiteral
where Base.Words : Collection, Base.Magnitude.Words : Collection {
FixedWidthInteger, _ExpressibleByBuiltinIntegerLiteral {

public typealias High = Base
public typealias Low = Base.Magnitude
Expand Down Expand Up @@ -235,7 +234,8 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
if Base.bitWidth < UInt.bitWidth {
_precondition(i == Index(.low(_low.startIndex)), "Invalid index")
_sanityCheck(2 * Base.bitWidth <= UInt.bitWidth)
return _low.first! | (_high.first! &<< Base.bitWidth._lowWord)
return _low[_low.startIndex] |
(_high[_high.startIndex] &<< Base.bitWidth._lowWord)
}
switch i._value {
case let .low(li): return _low[li]
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/Integers.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -1469,11 +1469,11 @@ public protocol BinaryInteger :

// FIXME: Should be `Words : Collection where Words.Element == UInt`
// See <rdar://problem/31798916> for why it isn't.
/// A type that represents the words of a binary integer.
/// A type that represents the words of a binary integer.
///
/// The `Words` type must conform to the `Collection` protocol with an
/// `Element` type of `UInt`.
associatedtype Words : Sequence where Words.Element == UInt
associatedtype Words : Sequence, _Indexable where Words.Element == UInt

/// A collection containing the words of this value's binary
/// representation, in order from the least significant to most significant.
Expand Down
2 changes: 1 addition & 1 deletion test/Compatibility/string_collection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ extension String : Collection { // expected-warning{{conformance of 'String' to
set { }
}

var isEmpty: Bool { return false } // expected-note{{var 'isEmpty' will not be used to satisfy the conformance to 'Collection'}}
var first: Character? { return nil } // expected-note{{var 'first' will not be used to satisfy the conformance to 'Collection'}}

}

Expand Down
12 changes: 12 additions & 0 deletions validation-test/stdlib/CollectionDiagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ struct GoodIndexable : Indexable {
func index(after i: Int) -> Int { return i + 1 }
var startIndex: Int { return 0 }
var endIndex: Int { return 0 }
var isEmpty: Bool { return true }
var count: Int { return 0 }

subscript(pos: Int) -> Int { return 0 }
subscript(bounds: Range<Int>) -> [Int] { return [] }
Expand All @@ -69,6 +71,8 @@ struct BadIndexable1 : Indexable {
func index(after i: Int) -> Int { return i + 1 }
var startIndex: Int { return 0 }
var endIndex: Int { return 0 }
var isEmpty: Bool { return true }
var count: Int { return 0 }

subscript(pos: Int) -> Int { return 0 }

Expand All @@ -80,6 +84,8 @@ struct BadIndexable1 : Indexable {
struct BadIndexable2 : Indexable {
var startIndex: Int { return 0 }
var endIndex: Int { return 0 }
var isEmpty: Bool { return true }
var count: Int { return 0 }

subscript(pos: Int) -> Int { return 0 }
subscript(bounds: Range<Int>) -> [Int] { return [] }
Expand All @@ -90,6 +96,8 @@ struct BadIndexable2 : Indexable {
struct GoodBidirectionalIndexable1 : BidirectionalIndexable {
var startIndex: Int { return 0 }
var endIndex: Int { return 0 }
var isEmpty: Bool { return true }
var count: Int { return 0 }
func index(after i: Int) -> Int { return i + 1 }
func index(before i: Int) -> Int { return i - 1 }

Expand All @@ -103,6 +111,8 @@ struct GoodBidirectionalIndexable1 : BidirectionalIndexable {
struct BadBidirectionalIndexable : BidirectionalIndexable {
var startIndex: Int { return 0 }
var endIndex: Int { return 0 }
var isEmpty: Bool { return true }
var count: Int { return 0 }

subscript(pos: Int) -> Int { return 0 }
subscript(bounds: Range<Int>) -> [Int] { return [] }
Expand All @@ -121,6 +131,8 @@ struct BadBidirectionalIndexable : BidirectionalIndexable {
struct RangeReplaceableCollection_SubSequence_IsDefaulted : RangeReplaceableCollection {
var startIndex: Int { fatalError() }
var endIndex: Int { fatalError() }
var isEmpty: Bool { return true }
var count: Int { return 0 }

subscript(pos: Int) -> Int { return 0 }

Expand Down