mirror of
https://github.com/apple/swift.git
synced 2026-03-04 18:24:35 +01:00
This change forces you to write ``@reparented` relationships
on an extension of a protocol, rather than on the protocol
itself.
The ProtocolConformance needs to be associated with some
GenericContext and IRGen expects it to be an ExtensionDecl.
That environment defines under what conditions the conformance
exists. We also need to define witnesses for the new parent's
requirements in an extension anyway, so it's a natural fit.
The previous workaround for this was kind of awful, as it'd
require searching all the protocol's extensions and "guess"
which extension they want to represent the conformance. While
we could try to synthesize an extension, there's two
challenges there:
1. Due to SuppressedAssociatedTypes, it's not so simple to
synthesize an unconstrained ExtensionDecl.
2. We currently rely on same-type requirements to pin the
associated types to particular witnesses of those requirements
in the extension. So it's not purely unconstrained! For example,
```
extension Seq: @reparented BorrowSeq where Iter == MyIter {}
```
The constraints that are disallowed (but not yet diagnosed)
are conditional conformance requirements, as the default
conformance for a reparenting cannot depend on those.
Thus, it's better that programmers to specify the extension.
99 lines
2.5 KiB
Swift
99 lines
2.5 KiB
Swift
public protocol BorrowingIter<Element>: ~Copyable, ~Escapable {
|
|
associatedtype Element: ~Copyable
|
|
|
|
// NOTE: Span has availability that blocks us from testing it here
|
|
mutating func nextThing() -> Element?
|
|
}
|
|
|
|
public protocol Iterable {
|
|
associatedtype Element
|
|
mutating func next() -> Element?
|
|
}
|
|
|
|
public struct LibraryLegacyIter: Iterable {
|
|
public typealias Element = String
|
|
public func next() -> String? { return "LibraryLegacyIter" }
|
|
}
|
|
|
|
public struct LibraryConformer: Seq {
|
|
public typealias Element = String
|
|
public typealias Iterator = LibraryLegacyIter
|
|
public func makeIterator() -> Iterator {
|
|
print("LibraryConformer.makeIterator()")
|
|
return Iterator()
|
|
}
|
|
}
|
|
|
|
#if BEFORE
|
|
public protocol Seq<Element> {
|
|
associatedtype Element
|
|
associatedtype Iterator: Iterable
|
|
func makeIterator() -> Iterator
|
|
}
|
|
#else
|
|
public protocol Seq<Element> {
|
|
associatedtype Element
|
|
associatedtype Iterator: Iterable
|
|
func makeIterator() -> Iterator
|
|
|
|
associatedtype BorrowingSeqIter: BorrowingIter<Element>, ~Copyable, ~Escapable = Adapter<Iterator>
|
|
}
|
|
|
|
@reparentable
|
|
public protocol BorrowingSeq<Element>: ~Copyable, ~Escapable {
|
|
associatedtype Element: ~Copyable
|
|
associatedtype BorrowingSeqIter: BorrowingIter<Element>, ~Copyable, ~Escapable
|
|
|
|
@_lifetime(borrow self)
|
|
func makeBorrowingSeqIter() -> BorrowingSeqIter
|
|
}
|
|
|
|
extension Seq : @reparented BorrowingSeq
|
|
where BorrowingSeqIter == Adapter<Iterator> {
|
|
public func makeBorrowingSeqIter() -> BorrowingSeqIter {
|
|
return Adapter(makeIterator())
|
|
}
|
|
}
|
|
|
|
public struct Adapter<Iterator: Iterable>: BorrowingIter {
|
|
public typealias Element = Iterator.Element
|
|
var iterator: Iterator
|
|
public init(_ iterator: Iterator) { self.iterator = iterator }
|
|
|
|
public mutating func nextThing() -> Element? {
|
|
print("Adapter invoking iterator.next()")
|
|
return iterator.next()!
|
|
}
|
|
}
|
|
|
|
public struct LibraryNewIter: BorrowingIter {
|
|
public func nextThing() -> String? {
|
|
return "LibraryNewIter"
|
|
}
|
|
}
|
|
|
|
extension LibraryConformer {
|
|
public typealias BorrowingSeqIter = LibraryNewIter
|
|
public func makeBorrowingSeqIter() -> BorrowingSeqIter {
|
|
print("LibraryConformer.makeBorrowingSeqIter()")
|
|
return BorrowingSeqIter()
|
|
}
|
|
}
|
|
#endif
|
|
|
|
public func libraryTest(_ x: some Seq) {
|
|
var iter = x.makeIterator()
|
|
print(iter.next()!)
|
|
#if !BEFORE
|
|
libraryTestNew(x)
|
|
#endif
|
|
}
|
|
|
|
#if !BEFORE
|
|
public func libraryTestNew(_ x: some BorrowingSeq) {
|
|
var borrowingIter = x.makeBorrowingSeqIter()
|
|
let answer = borrowingIter.nextThing()!
|
|
print(answer)
|
|
}
|
|
#endif
|