Hi all,
While SE-0346 is converging on a nice design, I think it's time to start discussing what associated types should be marked primary throughout the Standard Library.
To get things started, I've prepared a draft proposal (direct Markdown link, evolution PR) and an initial implementation that adds primary associated type declarations to 20 existing stdlib protocols.
The key part is this table; it lists all public protocols in the Standard Library that have associated type requirements, along with their proposed primary associated type (if any), as well as a list of other associated types.
Protocol | Primary | Others |
---|---|---|
Identifiable |
ID |
-- |
Sequence |
Element |
Iterator |
IteratorProtocol |
Element |
-- |
Collection |
Element |
Index , Iterator , SubSequence , Indices
|
MutableCollection |
Element |
Index , Iterator , SubSequence , Indices
|
BidirectionalCollection |
Element |
Index , Iterator , SubSequence , Indices
|
RandomAccessCollection |
Element |
Index , Iterator , SubSequence , Indices
|
RangeReplaceableCollection |
Element |
Index , Iterator , SubSequence , Indices
|
LazySequenceProtocol |
Elements |
Element , Iterator
|
LazyCollectionProtocol |
Elements |
Element , Index , Iterator , SubSequence , Indices
|
SetAlgebra |
Element |
ArrayLiteralElement |
OptionSet |
Element |
ArrayLiteralElement , RawValue
|
RawRepresentable |
RawValue |
-- |
RangeExpression |
Bound |
-- |
Strideable |
Stride |
-- |
Numeric |
-- |
IntegerLiteralType , Magnitude
|
SignedNumeric |
-- |
IntegerLiteralType , Magnitude
|
BinaryInteger |
-- |
IntegerLiteralType , Magnitude , Stride , Words
|
UnsignedInteger |
-- |
IntegerLiteralType , Magnitude , Stride , Words
|
SignedInteger |
-- |
IntegerLiteralType , Magnitude , Stride , Words
|
FixedWidthInteger |
-- |
IntegerLiteralType , Magnitude , Stride , Words
|
FloatingPoint |
-- |
IntegerLiteralType , Magnitude , Stride , Exponent
|
BinaryFloatingPoint |
-- |
IntegerLiteralType , FloatLiteralType , Magnitude , Stride , Exponent , RawSignificand , RawExponent
|
SIMD |
Scalar |
ArrayLiteralElement , MaskStorage
|
SIMDStorage |
-- | Scalar |
SIMDScalar |
-- |
SIMDMaskScalar , SIMD2Storage , SIMD4Storage , ..., SIMD64Storage
|
Clock |
Instant |
-- |
InstantProtocol |
Duration |
-- |
AsyncIteratorProtocol |
-- (1) | Element |
AsyncSequence |
-- (1) |
AsyncIterator , Element
|
GlobalActor |
-- | ActorType |
KeyedEncodingContainerProtocol |
-- (4) | Key |
KeyedDecodingContainerProtocol |
-- (4) | Key |
ExpressibleByIntegerLiteral |
-- | IntegerLiteralType |
ExpressibleByFloatLiteral |
-- | FloatLiteralType |
ExpressibleByBooleanLiteral |
-- | BooleanLiteralType |
ExpressibleByUnicodeScalarLiteral |
-- | UnicodeScalarLiteralType |
ExpressibleByExtended- GraphemeClusterLiteral
|
-- |
UnicodeScalarLiteralType , ExtendedGraphemeClusterLiteralType
|
ExpressibleByStringLiteral |
-- |
UnicodeScalarLiteralType , ExtendedGraphemeClusterLiteralType , StringLiteralType
|
ExpressibleByStringInterpolation |
-- |
UnicodeScalarLiteralType , ExtendedGraphemeClusterLiteralType , StringLiteralType , StringInterPolation
|
ExpressibleByArrayLiteral |
-- | ArrayLiteralElement |
ExpressibleByDictionaryLiteral |
-- |
Key , Value
|
StringInterpolationProtocol |
-- | StringLiteralType |
Unicode.Encoding |
-- |
CodeUnit , EncodedScalar , ForwardParser , ReverseParser
|
UnicodeCodec |
-- |
CodeUnit , EncodedScalar , ForwardParser , ReverseParser
|
Unicode.Parser |
-- | Encoding |
StringProtocol |
-- |
Element , Index , Iterator , SubSequence , Indices , UnicodeScalarLiteralType , ExtendedGraphemeClusterLiteralType , StringLiteralType , StringInterPolation , UTF8View , UTF16View , UnicodeScalarView
|
CaseIterable |
-- | AllCases |
Notes:
(1) AsyncSequence
and AsyncIteratorProtocol
logically ought to have Element
as their primary associated type. However, we have ongoing evolution discussions about adding a precise error type to these. If those discussions bear fruit, then the new Error
associated type would need to also be marked primary. To prevent source compatibility complications, adding primary associated types to these two protocols is deferred to a future proposal.
Note that once we add primary associated types to a protocol, we will be forever stuck with them -- removing primaries, reordering the list, or (as of SE-0346) extending an existing list with a new type would all be source breaking changes.
Notable points:
-
AsyncSequence
andAsyncIteratorProtocol
are intentional omissions -- given that there are ongoing discussions about adding anError
type to these, it seems prudent to leave these out until we know more. (Per SE-0346, addingError
as a second primary would be a source-breaking change.) -
LazySequenceProtocol
andLazyCollectionProtocol
useElements
as their primary associated type, notElement
. The idea here is that if we spell outLazyCollectionProtocol
, we probably want to also say something about the wrapped collection, not just its element type -- for example, by constraining it to random access collections usingsome LazyCollectionProtocol<some RandomAccessCollection<String>>
. -
We do not want protocols to declare multiple primaries unless we wanted to force every use site to list all of them, even if they only care about some. (E.g., if for some reason
Collection
declaredElement
andIndex
as its primaries, then every single use site that wanted to use the bracketed syntax would need to spell out an index type -- which would be quite unwieldy.) -
KeyedEncodingContainerProtocol
andKeyedDecodingContainerProtocol
originally hadKey
as their primary associated type. This was removed during the course of this discussion.
As of Swift 5.6, the following public protocols don't have associated type requirements, so they are outside of the scope of this proposal.
Equatable, Hashable, Comparable, Error, AdditiveArithmetic,
DurationProtocol, Sendable, UnsafeSendable, Actor, AnyActor, Executor,
SerialExecutor, Encodable, Decodable, Encoder, Decoder,
UnkeyedEncodingContainer, UnkeyedDecodingContainer,
SingleValueEncodingContainer, SingleValueDecodingContainer,
ExpressibleByNilLiteral, CodingKeyRepresentable,
CustomStringConvertible, LosslessStringConvertible, TextOutputStream,
TextOutputStreamable, CustomPlaygroundDisplayConvertible,
CustomReflectable, CustomLeafReflectable, MirrorPath,
RandomNumberGenerator, CVarArg
Feedback would be most appreciated -- did I miss anything?