natevw
natevw

Reputation: 17902

Why can't I stride over all Strideable types in Swift?

I get an error:

Cannot invoke 'stride' with an argument list of type '(from: MyType, to: MyType, by: MyType)'

when I try to compile this code:

typealias MyType = UInt64

let a: MyType = 0
let b: MyType = 100
let c: MyType = 10

for i in stride(from: a, to: b, by: c) {
  // …
}

What's odd is that when I jump to the definition of Swift.stride it shows that stride should take basically any Strideable:

public func stride<T>(from start: T, to end: T, by stride: T.Stride) -> StrideTo<T> where T : Strideable

But if I add extension MyType: Strideable {} to my code, it complains that "Conformance of 'UInt64' to protocol 'Strideable' was already stated in the type's module 'Swift'"!

Why won't it let me stride over anything but an Int?

Upvotes: 1

Views: 241

Answers (1)

natevw
natevw

Reputation: 17902

The trouble is with the by stride: parameter. Upon closer inspection, its expected type is not T, but T.Stride — and UInt64.Stride is not typealiased to UInt64, but to Int!

The following code satisfies the type requirements of stride's third parameter:

typealias MyType = UInt64

let a: MyType = 0
let b: MyType = 100
let c: MyType = 10

for i in stride(from: a, to: b, by: Int(c)) {
  // …
}

(If practical in your code, I would recommend typing c as an Int initially instead. In my original context that didn't make as much sense as "casting" it only during its usage with stride.)

Upvotes: 3

Related Questions