Allow `@retroactive` to be applied to module-local protocols that imply external conformances

Allow @retroactive to be applied to module-local protocols that imply external conformances

View this proposal on GitHub

  • Proposal: SE-NNNN
  • Author: Diana Ma
  • Review Manager: TBD
  • Status: Pitch

Introduction

Currently, when a protocol defined in the current module refines external protocols, conforming an external type to this local protocol requires spelling out each implied protocol conformance at the conformance site with the @retroactive attribute applied to the name of each implied protocol. This proposal seeks to allow a single @retroactive attribute applied to a conformance to a local protocol to imply @retroactive conformances to all its external implied protocols.

Motivation

The current requirement to enumerate all external protocol conformances individually with @retroactive is verbose and scales multiplicatively with the number of implied protocols and conformed types. Allowing a single @retroactive on the name of the local protocol would streamline such retroactive conformances and make files with large lists of conforming types (“conformance pages”) more compact and expressive.

Proposed Solution

In this section, module may refer to a collection of modules treated as a resilence unit (e.g., can access package-visible declarations).

We would permit attaching @retroactive to an unconditional conformance to a protocol defined in the same module, if that protocol refines protocols defined outside the module. The compiler would recognize that conforming to the local protocol necessarily implies conformances to the external protocols, and would treat the attribute as if it were applied to each of the implied external protocols.

Detailed Design

  • The compiler will accept a single @retroactive attribute on a conformance to a protocol defined in the current module, if that protocol refines external protocols.
  • The conformance will be treated as retroactive for all implied external protocols.
  • The @retroactive attribute is only valid when the local protocol’s inheritance tree includes protocols external to the module.
  • Only unconditional conformances are eligible for this syntax.

Example

Today:

extension ExternalType: @retroactive ExternalProtocol1, @retroactive ExternalProtocol2, LocalProtocol {}

Each external protocol must be listed with @retroactive.

With this proposal:

extension ExternalType: @retroactive LocalProtocol {}

Where LocalProtocol (defined in this module) refines ExternalProtocol1 and ExternalProtocol2.

public protocol LocalProtocol: ExternalProtocol1, ExternalProtocol2 {}

Impact on Existing Code

This is an additive change and does not affect existing code.

Alternatives Considered

Status Quo

Continue requiring explicit retroactive conformances for each external protocol.

Protocol Composition with @retroactive

Require spelling out individual implied conformances, but allow a single @retroactive attribute to be applied to an entire protocol composition clause. This has already been implemented in Swift 6.2.

Acknowledgments

Thanks to everyone who contributed feedback and motivation for this proposal.

17 Likes