[Pitch] Get all the protocols a type supports

(Daryle Walker) #1

I mentioned this in another thread recently. Here’s a more formal pitch.

Query a Type on Its Protocols
Proposal: SE-NNNN <file:///Users/daryle/Documents/NNNN-all-protocols-list.md>
Authors: Daryle Walker <https://github.com/CTMacUser>, Author 2 <https://github.com/swiftdev>
Review Manager: TBD
Status: Awaiting review
This proposal adds a type-alias operator for all the protocols a given type supports.

Swift-evolution thread: Discussion thread topic for that proposal <https://lists.swift.org/pipermail/swift-evolution/>
Manipulations of protocols with types are explicitly user-driven. A protocol has to be associated with a type by a user at the type's primary definition block or in an extension's definition block. Protocols have to be combined by the user with composition or inheritance. There is currently no way to create or use protocols without the user knowing all the protocols involved in advance.

There is (at least) one case where the user can't know all the protocols in advance. It's when wanting to know what protocols a given type already has. Currently, that's not very useful; an implicit list of all the protocols of a type only helps when making a item conform to the protocols of another type. A user can't just manually walk all the protocols in the type's definition, because others may be added through extensions. Those other protocol introductions are walkable too, but they would have to be manually maintained (looking through all the source code, not just the type's primary file) after every source-code change.

Proposed solution
Although the list of protocols for a given type is (practically) open from the user's perspective, it's closed from the compiler/linker's perspective. Therefore, the list can be mechanically generated and updated.

The list will be represented as a type-alias. The alias is expressed by a new special operator that takes the source type as its only input. The alias acts like any other type-alias to a protocol; it can be used as a conformance source and can have .Protocol tacked on at the end for metatype analysis.

func integerTesting(_ sample: #protocols(Int32)) -> Int {
    // Use "sample," which we know follows all of the same protocols as "Int32".
    // Examples are "Int" and "Int64".
    // (Note we can't go the other way because "Int32" doesn't support "MirrorPath"!)
The type accounting tables the compiler (and maybe linker) have to build during translation will get all the protocols a particular type conforms to. Then the compiler can add a new entry, the same as protocol compositions, and list all the discovered protocols in the entry's sub-protocol list. Since there is a new order dependency added (before using #protocols(MyType), the compiler has to analyze MyType and all possible affecting extensions throughout the program, then create a new protocol composition to insert), recursion loops may be possible [not sure how myself]. Loops, or nested computing of all-protocol lists that are too deep, should raise a compile-time error (too many resources used).

Using the #protocols operator on a type that doesn't conform to any protocols will return Any. Using the operator on a protocol returns that same protocol.

Detailed design
Add to "Grammar of a Type":

type → #protocols ( type )
Source compatibility
The changes should be strictly additive, including one new keyword.

Effect on ABI stability
The ABI should not be affected. The new type expression acts like a protocol composition, and the protocols making up that composition are determined at compile [and/or link?] time.

Effect on API resilience
This feature most likely won't be used in standard library code, so the API won't be affected. Anything that uses an all-protocol list on a library type will get affected during library revisions.

Alternatives considered
The alternative is to not add this operator. Then users still research what protocols a target type uses, manually add said protocols at the appropriate place, and hope that some extension declaration wasn't missed.


Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com