The return types for stride(from: to: by:) and stride(from: through: by:), StrideTo and StrideThrough respectively, are only Sequences, not Collections. This was caused by a bug in conditional conformance, as mentioned in the preamble to the commented-out Collection-conformance code. Since SR-6474 is now fixed, can we now make them collections?

Added as SR-13492 ("Make StrideTo and StrideThrough conform to (RandomAccess)Collection").

Is there any way to push this? With swift-testing, this would be a welcome addition, as test arguments must be collections. With this conformance, we could pass strides directly:

@Test(arguments: stride(from: 9.0, through: 24.0, by: 2.5))
func testWithSizes(size: Double) { … }

As of Xcode 16 beta 4 this is a error.

2 Likes

Remember that you can stride over non-numeric types so long as they have some distance function. It is non-trivial to implement Collection conformance for the general case (actually, as I recall from last I looked at it, the protocol doesn't have the necessary requirements to do so at all). And since a type can only conform to a protocol in one way, if we implement for only a subset of strides we affirmatively deny conformance to all others.

On the flip side: can @Test(arguments:) take just a sequence instead?

1 Like

@grynspan provided a rationale for this in Idea: make it possible to pass permutations of collections to `arguments` - #3 by grynspan

It's necessary for the Swift Testing interface to constrain arguments to Collection because Sequence does not indicate if it is safe to iterate it more than once, and Swift Testing may need to iterate over the arguments more than once in some circumstances.

I don’t know enough about the standard library and the compiler to understand all the implications. The original post and linked issue made it sound like it was an oversight. But I take your word that it’s not!

For now, I’ve helped myself with an alias that makes the code compile and seems to work just fine:

public func stride<T>(from: T, through: T, by: T.Stride) -> [T] where T : Strideable {
	Swift.stride(from: from, through: through, by: by).flatMap { [$0] }
}

Sure, that works, but it is a rather elaborate way of writing just Array(stride(...)).

1 Like