Files
swift-mirror/validation-test/Evolution/test_protocol_add_reparented_seq.swift
Kavon Farvardin 006a0a494a Reparenting: require an extension
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.
2026-02-03 16:40:21 -08:00

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()