Files
swift-mirror/test/Sema/reparenting.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

68 lines
2.5 KiB
Swift

// RUN: %target-typecheck-verify-swift -enable-experimental-feature Reparenting
// REQUIRES: objc_interop
// REQUIRES: swift_feature_Reparenting
@reparentable
protocol Q {}
@reparentable
protocol R {}
protocol P {}
extension P : @reparented Q {}
protocol P2 {}
extension P2 : @reparented Q, @reparented R {}
protocol DirectlyOnProto: @reparented R {}
// expected-error@-1 {{'@reparented' only applies in inheritance clause of a protocol extension}}
class Whatever: @reparented AnyObject {}
// expected-error @-1 {{'@reparented' only applies in inheritance clause of a protocol extension}}
protocol Invalid {
associatedtype A: @reparented Q
// expected-error @-1 {{'@reparented' only applies in inheritance clause of a protocol extension}}
}
extension Invalid: @reparented AnyObject {}
// expected-error @-1 {{'@reparented' cannot apply to non-protocol type 'AnyObject'}}
extension Invalid: @reparented Whatever {}
// expected-error @-1 {{'@reparented' cannot apply to non-protocol type 'Whatever'}}
extension Invalid: @reparented P {}
// expected-error @-1 {{'@reparented' cannot apply to 'P' unless it is declared to be '@reparentable'}}
extension Invalid: @reparented Q & R {}
// expected-error @-1 {{'@reparented' cannot apply to non-protocol type 'Q & R'}}
@objc protocol ObjCProto {}
extension ObjCProto: @reparented Q {}
// expected-error @-1 {{@objc protocol 'ObjCProto' cannot be '@reparented'}}
// The reparentable protocol shouldn't directly inherit from some other protocol that requires a witness table.
public protocol GrandParentJiji {
associatedtype Element
}
@reparentable
public protocol ParentJiji: GrandParentJiji {} // expected-note {{'Jiji' does not conform to inherited protocol 'GrandParentJiji'}}
public protocol Jiji {
associatedtype Element
}
extension Jiji: @reparented ParentJiji {} // expected-error {{'Jiji' cannot conform to 'GrandParentJiji'}}
// expected-note@-1 {{only concrete types such as structs, enums and classes can conform to protocols}}
public protocol Pumpkin {}
@reparentable public protocol AnyObjParent: AnyObject {}
@reparentable public protocol ActorParent: Actor {}
@reparentable public protocol SendableParent: Sendable {}
extension Pumpkin: @reparented AnyObjParent {} // expected-error {{non-class type 'Pumpkin' cannot conform to class protocol 'AnyObjParent'}}
extension Pumpkin: @reparented ActorParent {} // expected-error {{non-class type 'Pumpkin' cannot conform to class protocol 'ActorParent'}}
extension Pumpkin: @reparented SendableParent {}