I have a sequence to do arithmetic progressions:
public struct ArithmeticallyProgressingSequence<Element: AdditiveArithmetic>: LazySequenceProtocol {
public let distance: Element
public let start: Element
@inlinable
public init(start: Element, distance: Element) {
self.start = start
self.distance = distance
}
public struct Iterator: IteratorProtocol {
public let distance: Element
@usableFromInline
var upcoming: Element
@inlinable
init(start: Element, distance: Element) {
upcoming = start
self.distance = distance
}
@inlinable
public mutating func next() -> Element? {
defer { upcoming += distance }
return upcoming
}
}
@inlinable
public __consuming func makeIterator() -> Iterator {
return Iterator(start: start, distance: distance)
}
}
with a specialty initializer when the Element
is also Numeric
:
extension ArithmeticallyProgressingSequence where Element: Numeric {
@inlinable
public init(factor: Element, startingMultiple: Element, offset: Element = 0) {
precondition(offset.magnitude < factor.magnitude)
self.init(start: factor * startingMultiple + offset, distance: factor)
}
}
but when I used the type in a client where the iterated variable was an integer type that conformed to BinaryInteger
, only the primary initializer was suggested. Since BinaryInteger
refines Numeric
, which refines AdditiveArithmetic
, I should have gotten both initializers as options. In fact, writing in the secondary initializer's labels makes the compiler suggest a fix-it to change the labels back to the primary initializer's. Why isn't the compiler recognizing my element type qualifies for both initializers?
The lines from the client:
else {
// The error with the second initializer: "Incorrect argument labels in call (have 'factor:startingMultiple:', expected 'start:distance:')"
// Fix-it: "Replace 'factor: upcoming * upcoming, startingMultiple' with 'start: upcoming * upcoming, distance'"
primeMultiples.append(Advancer(factor: upcoming * upcoming, startingMultiple: upcoming))
return true
}
where upcoming
is of type Integer
, which is the generic argument:
struct MyType<Integer: BinaryInteger> { /*...*/ }