Is this problem with intermediate Sequence protocols only intermittent?

collection
(Daryle Walker) #1

I'm trying to add intermediate protocols to represent multi-pass sequences:

public protocol RepeatableSequence: Sequence {}
public protocol PersistentSequence: RepeatableSequence {}

Then I changed the base protocol for Collection:

public protocol Collection: PersistentSequence { /*...*/ }

And I'm running "./utils/build-script --release-debuginfo --test" to make sure everything is alright. I ran the test right after adding the two new protocols, and there were no problems. Now I get a bunch of:

/Volumes/ExtremeSSD/swift-source/swift/stdlib/public/core/Range.swift:189:1: error: conditional conformance of type 'Range<Bound>' to protocol 'Collection' does not imply conformance to inherited protocol 'PersistentSequence'
extension Range: Collection, BidirectionalCollection, RandomAccessCollection
^
/Volumes/ExtremeSSD/swift-source/swift/stdlib/public/core/Range.swift:189:1: note: did you mean to explicitly state the conformance like 'extension Range: PersistentSequence where ...'?
extension Range: Collection, BidirectionalCollection, RandomAccessCollection
^
/Volumes/ExtremeSSD/swift-source/swift/stdlib/public/core/Range.swift:189:1: error: conditional conformance of type 'Range<Bound>' to protocol 'Collection' does not imply conformance to inherited protocol 'RepeatableSequence'
extension Range: Collection, BidirectionalCollection, RandomAccessCollection
^
/Volumes/ExtremeSSD/swift-source/swift/stdlib/public/core/Range.swift:189:1: note: did you mean to explicitly state the conformance like 'extension Range: RepeatableSequence where ...'?
extension Range: Collection, BidirectionalCollection, RandomAccessCollection
^

with similar results for ClosedRange, LazyDropWhileSequence, LazyFilterSequence, FlattenSequence, LazySequence, LazyMapSequence, and LazyPrefixWhileSequence. I don't know if the other included types are OK, or the tests aborted before getting that far. Do I have to add "override" declarations in the new protocols' bodies? Or manually add conformance to each conforming type? Something else?

(Xiaodi Wu) #2

This is not an ABI-compatible change and cannot be made to the standard library at this point.

Conditional conformances require each conformance to be stated explicitly. You will need to add new conformances manually in each such case. But again, this is ABI-incompatible.

1 Like
(Daryle Walker) #3

So changing a protocol's base protocol is an ABI-incompatible change, even done as an intermediate type instead of a replacement? Does the same apply to changing the base class for a class type (to a new intermediate class)?

Where is it stated that this would be an ABI-incompatible change? I want to add a reference to that to the proposal draft.

So, we'll need either an ABI v2 or a Sequence2/Collection2/etc. and transition everything over?

Also so, a solution to the Dictionary-and-Set-aren't-really-Sequences problem that involves a new base protocol to go below Sequence would get the same issues? (Obviously this would require the C++ code that translates for-in statements to change the protocol it searches for to the new base.)

Hmm, maybe we're doing this stability stuff years too soon?...

(Xiaodi Wu) #4

Changing the protocol hierarchy affects the ABI: this is why SE-0233 ("Make Numeric refine a new AdditiveArithmetic protocol") had to be considered before Swift 5 was released. The protocol hierarchy for collections is now frozen for Swift.

(Daryle Walker) #5

So to do a Collections-version-3 (I think the now-frozen one is v2, right?), we need:

  1. An @objectName(identifier) attribute that is like the current objc but can be used for non-Objective-C items in Swift.

  2. Use the above attribute to externally rename the old protocols while not breaking the ABI and letting the new code reuse the old names.

     @objectName(Sequence)
     public protocol OldAndBusted {
         // What the current Sequence has here
     }
    
     @objectName(TheNewHotness)
     public protocol Sequence: IterableSet {
         // Put @CTMacUser's reinterpretation of Sequence here 
     }
    

    where IterableSet is like current-Sequence without the linearity semantics (and the methods that assume linearity, like prefix). I once wondered how to make the renditions to for-in loops recognize two different hierarchies, IterableSet and Sequence. Then I realized that doing that isn't necessary if you make Sequence refine IterableSet. But now you're telling me that, due to the ABI freeze, we will need to do that after all?!

I've read various people here mentioned resilient (protocols(?) and) types. If type-resilience is added, then a Collections-version-3 hierarchy is added, would the resilience let us make edits to Cv3 hierarchy safely? Or would we still have to make an incompatible Collections-version-4 hierarchy if we discovered that we messed up yet again?

Hmm, for something more useful to Swift, I ought to make a separate thread on @objectName.

Overriding object-code names