mirror of
https://github.com/apple/swift.git
synced 2026-02-27 18:26:24 +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.
69 lines
2.0 KiB
Swift
69 lines
2.0 KiB
Swift
// RUN: %target-resilience-test --skip-application-back-deploy \
|
|
// RUN: --experimental-features 'Reparenting,SuppressedAssociatedTypesWithDefaults,Lifetimes,LifetimeDependence'
|
|
|
|
// REQUIRES: executable_test
|
|
|
|
// REQUIRES: swift_feature_Reparenting
|
|
// REQUIRES: swift_feature_SuppressedAssociatedTypesWithDefaults
|
|
// REQUIRES: swift_feature_Lifetimes
|
|
// REQUIRES: swift_feature_LifetimeDependence
|
|
|
|
import StdlibUnittest
|
|
import protocol_add_reparented_seq
|
|
|
|
public struct LegacyIter: Iterable {
|
|
public typealias Element = String
|
|
public func next() -> String? { "Client's LegacyIter" }
|
|
}
|
|
|
|
struct LegacyClientConformer: Seq {
|
|
typealias Element = String
|
|
typealias Iterator = LegacyIter
|
|
func makeIterator() -> Iterator {
|
|
print("LegacyClientConformer.makeIterator()")
|
|
return Iterator()
|
|
}
|
|
}
|
|
|
|
#if !BEFORE
|
|
public struct FreshIter: BorrowingIter {
|
|
public func nextThing() -> String? { return "Client's FreshIter" }
|
|
}
|
|
|
|
struct BorrowingSeqAwareConformer: Seq {
|
|
typealias Element = String
|
|
typealias Iterator = LegacyIter
|
|
public func makeIterator() -> Iterator {
|
|
print("BorrowingSeqAwareConformer.makeIterator()")
|
|
return Iterator()
|
|
}
|
|
|
|
typealias BorrowingSeqIter = FreshIter
|
|
public func makeBorrowingSeqIter() -> BorrowingSeqIter {
|
|
print("BorrowingSeqAwareConformer.makeBorrowingSeqIter()")
|
|
return BorrowingSeqIter()
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
var ProtocolAddReparentedTestSeq = TestSuite("ProtocolAddReparentedSeq")
|
|
|
|
// FIXME: would be better if this was validating that we invoked the
|
|
// correct witnesses, etc, rather than just seeing if it crashes.
|
|
// Could verify things by having the Element type be an Enum that
|
|
// encodes the same purpose (including nesting) that the String does.
|
|
ProtocolAddReparentedTestSeq.test("Does Not Crash") {
|
|
libraryTest(LegacyClientConformer())
|
|
#if !BEFORE
|
|
print("-----")
|
|
libraryTest(BorrowingSeqAwareConformer())
|
|
#endif
|
|
}
|
|
|
|
// FIXME: add a "Collection" protocol under Seq in the library to test that.
|
|
// Also test a protocol on client side that extends Seq too.
|
|
|
|
runAllTests()
|