RangeReplaceableCollection

Has the Standard Library been modified to extend RangeReplaceableCollection?

The release notes for MacOS Catalina Beta 5 report:

The RangeReplaceableCollection protocol is extended to include a remove(atOffsets:) method and the MutableCollection protocol is extended to include a move(fromOffsets:toOffset:) method. Each new method takes IndexSet instances that you use with the onMove(perform:) and onDelete(perform:) modifiers on ForEach views. (51991601)

1 Like

It's in the SwiftUI section of the report, which suggests that the extension is in the SwiftUI framework and not Standard Library

Shouldn't we open an issue? Is it not a "sin", for a given module A, to publicly extend a type defined in another module B with methods whose signature does not involve types from A?

// In module A
import B
extension B.SomeType {
    // Well-behaved
    public func doStuff(_ x: A.Stuff) // OK

    // Mis-behaved
    public func doStuff() 
    public func doStuff(_ x: Swift.Int)
    public func doStuff(_ x: Foundation.IndexSet)
    public func doStuff(_ x: SomeOtherModule.Stuff)
}

To me, it looks like SwiftUI may well use this extension internally, no problem, but that it should not be public.

Am I correct? Or do I forget things like inlining and ABI stability?

No. The "sin" is in conforming types you don't own to protocols you don't own. Extending a protocol with new methods is not considered problematic, whether you own any of the types involved.

1 Like

You are right @Avi, you have described the classic sin.

But aren't we looking at another sin, then? Consider this other current discussion, which talks about removing indices. What will happen when the Standard Library defines the same extension, and a user imports Foundation? Or, more precisely, if Foundation defines the same extension (after all, IndexSet is Foundation's property)? Won't the compiler complain with ambiguity errors, due to two conflicting implementations?

Should SwiftUI be allowed to step on Foundation's "natural" territory?

Yes, that's another situation we have with the ability to extend types we don't own. We would need to overhaul, in a very source-breaking way, the current access controls to close this hole. Any two libraries can extend a common type (from the stdlib or any other source) in incompatible ways. This isn't limited to just the type owner and a consuming framework.

Or we need a way to disambiguate at the call site.

Both SwiftUI and Foundation are being owned by apple, so they can remove the extension from SwiftUI at the same time they add it to Foundation. I have no idea how that would affect ABI, but it should be source compatible because SwiftUI and Foundation are always shipped together

1 Like

And on those platforms where this is not true, SwiftUI doesn't exist, so the extension doesn't either.

2 Likes

Thanks @cukr and @Avi. I don't see any trouble now.

1 Like

The change appears to be in the Standard Library itself, rather than in SwiftUI. Or, at least, in the Standard Library documentation.

1 Like

What problems does this create? I have run into several situations where it would be extremely convenient to add conformances in a separate module, and it's always been a point of frustration not to be able to do this.

You can do that, so I'm not sure what trouble you ran into.

The reason it's considered a sin is that your code is brittle, as the owners of the types can't possibly consider your extensions when changing their code.

See: Retroactive Conformances vs. Swift-in-the-OS

2 Likes

If I try to publicly extend a type with a protocol conformance I get this error:

'public' modifier cannot be used with extensions that declare protocol conformances

I think that's because it's superfluous. If the protocol is public, the conformance will be, and if it's not, you can't make the extension public anyway.

Actually, with a little more digging, it appears the remove(atOffsets:) method is implemented in the Foundation framework. So, the documentation's listing of the method raises the question: Should the "official" Swift Standard Library documentation include references to methods contained in extensions implemented via frameworks? The documentation notes that the method is part of the SwiftUI framework, but that approach to documentation seems awkward--perhaps a bit Apple-centric.

The applying(_:) method is anticipated to be included in the Standard Library, but the pending amendment has not yet been accepted AFIK (Active Review (June 19 - 25 2019). Of course, it is a sure thing that it will be accepted. Certainly, the formality of acceptance will catch up soon. @Douglas_Gregor

Extensions to standard library protocols and types end up getting listed in the standard library documentation, by and large.

I suppose it is convenient to handle the documentation in that fashion, but it sure feels like a fork in the language. One language set when working with Apple OS, and another set when elsewhere.

I love SwiftUI and Combine, and admire the incredible, herculean work that those teams presently are engaged in. But, I am concerned about the implications of their decisions on the future development of the language.

For instance, one could imagine a future in which there would exist a UserInterface framework, with that framework providing (i) types to specify universal UI elements, and (ii) a set of protocols to provide an interface between those universal types and any given OS, with the platform provider (or the Swift-on-Linux project) to write types that conform to the interface protocols. SwiftUI may be a big step down that road; or it may, through inertia and/or due to naming collisions and/or for other reasons, become an impediment to growth in that sort of direction or other directions. I'd appreciate the thoughts of the community on that topic, but perhaps that discussion should be saved for some other thread.

1 Like