I think I found another misapplied implementation

This happened on both Xcode 9.2 (Swift 4.0) and 9.3beta (Swift 4.1). I’m trying out a BitArray. I added Collection semantics with no problem, then MutableCollection, BidirectionalCollection, and RandomAccessCollection. When I added RangeReplaceableCollection, the S4.0 compiler only complained about needing a default initializer, it didn’t post anything about replaceSubrange(_: with:). In my test code, I called the default initializer and it worked. When I added a call to replaceSubrange, instead of complaining that I still didn’t provide an implementation, Xcode went ahead to build & test, leading to a crash. In Xcode 9.3beta, the error:

Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeef3ffff8)

appeared on the line with the call to replaceSubrange. For Xcode 9.2, I got the same error line. Note that this is the version of replaceSubrange that takes a generic RangeExpression; the main version, which takes a Range<Index> for its first parameter, was never suggested.

Looking up the exact definition of the regular replaceSubrange and manually putting in my type’s (extension) definition fixes the problem. As I said, this version of replaceSubrange was never suggested, so I don’t know if it’s an auto-complete problem, or an accidental recursive default implementation (like the UInt72 type had earlier), or what.

The default implementation of generic replaceSubrange has a line that’s intended to call the non-generic method. However, in the absence of such an implementation it seems like it simply calls itself recursively.

Unless I’m mistaken, the compiler very astutely figures out that the signature for the generic method is acceptable for fulfilling the non-generic requirement. The temptation will be to find some hack to make an exception to the rules about generic implementations fulfilling non-generic requirements; I think that’d be the wrong way to go as this is quite useful in scenarios where there isn’t this sort of default implementation problem.

I know that @codafi has a PR for diagnosing infinite recursion. Ideally, somewhere in the compiler, there’d be logic to determine whether a default implementation is infinitely recursive for a conforming type, and if so, to consider if that’s the result of a generic method calling a nongeneric method of the same name, and then specifically in that scenario only, to deem the nongeneric method not implemented.

On a more meta note, can we keep bug reports to https://bugs.swift.org? It’s more suited for tracking these issues anyway.

2 Likes

@Nicole_Jacque Likewise about moving this thread to the standard library category.