1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
|
\documentclass[../generics]{subfiles}
\begin{document}
\chapter{Generic Declarations}\label{generic declarations}
\IndexDefinition{generic declaration}
\index{generic parameter list}
\IndexDefinition{generic type alias}
\lettrine{V}{arious kinds of declarations} can have a generic parameter list and a trailing \texttt{where} clause, and by looking at their syntax and semantics, our foray into generics can begin in earnest. In this chapter, we will explore the so-called \emph{generic declarations}:
\begin{itemize}
\item classes, structs and enums,
\item type aliases,
\item functions,
\item constructors,
\item subscripts,
\item extensions.
\end{itemize}
\IndexDefinition{parsed generic parameter list}
\Index{protocol Self type@protocol \texttt{Self} type}
\index{opaque parameter}
The \emph{parsed} generic parameter list of a declaration is what's written in source, with the familiar \texttt{<...>} syntax following the declaration name. The declaration's complete generic parameter list includes the parsed generic parameter list together with any implicit generic parameters:
\begin{enumerate}
\item Functions and subscripts may have a parsed generic parameter list, or they can declare opaque parameters with the \texttt{some} keyword, or both (Section~\ref{opaque parameters}).
\item Protocols always have a single implicit \texttt{Self} generic parameter, and no parsed generic parameter list (Section~\ref{protocols}).
\item Extensions always have an implicit set of generic parameters inherited from the extended type, and no parsed generic parameter list (Chapter~\ref{extension binding}).
\end{enumerate}
Parsed generic parameters, the protocol \texttt{Self} type, and the implicit generic parameters of an extension all have names that remain in scope for the entire source range of the generic declaration. Generic parameters introduced by opaque parameter declarations are unnamed; only the value declared by the opaque parameter has a name.
\index{declaration context}
\IndexDefinition{generic context}
All generic declarations are declaration contexts, because they contain their generic parameter declarations. A \emph{generic context} is a declaration context where at least one parent context is a generic declaration. Note the subtle distinction in the meaning of ``generic'' when talking about declarations and declaration contexts; a declaration is generic only if it has generic parameters of its own, whereas a declaration context being a generic context is a transitive properly inherited from the parent context.
\IndexDefinition{depth}
\IndexDefinition{index}
Inside a generic context, unqualified name lookup will find all outer generic parameters. Each generic parameter is therefore uniquely identified within a generic context by its \emph{depth} and \emph{index}:
\begin{itemize}
\item The depth identifies a specific generic declaration, starting from zero for the top-level generic declaration and incrementing for each nested generic declaration.
\item The index identifies a generic parameter within a single generic parameter list.
\end{itemize}
\index{sugared type}
The declared interface type of a generic parameter declaration is a sugared type that prints as the generic parameter name. The canonical type of this type only stores the depth and index. The notation for a canonical generic parameter type is \ttgp{d}{i}, where \texttt{d} is the depth and \texttt{i} is the index.
\begin{listing}\captionabove{Two nested generic declarations}\label{linkedlistexample}
\begin{Verbatim}
enum LinkedList<Element> {
case none
indirect case entry(Element, LinkedList<Element>)
func mapReduce<T, A>(_ f: (Element) -> T,
_ m: (A, T) -> A,
_ a: A) -> A {
switch self {
case .none:
return a
case .entry(let x, let xs):
return m(xs.mapReduce(f, m, a), f(x))
}
}
\end{Verbatim}
\end{listing}
\begin{example}
Listing~\ref{linkedlistexample} declares a \texttt{LinkedList} type with a single generic parameter named \texttt{Element}, and a \texttt{mapReduce()} method with two generic parameters named \texttt{T} and \texttt{A}. All three generic parameters are visible from inside the method:
\begin{quote}
\begin{tabular}{|l|l|l|l|}
\hline
Name&Depth&Index&Canonical type\\
\hline
\texttt{Element}&0&0&\ttgp{0}{0}\\
\texttt{T}&1&0&\ttgp{1}{0}\\
\texttt{A}&1&1&\ttgp{1}{1}\\
\hline
\end{tabular}
\end{quote}
\end{example}
\paragraph{History}
The list of generic declaration kinds at the beginning of this chapter has grown two new additions over time: generic type aliases were introduced in Swift 3 \cite{se0048}, while generic subscripts were introduced in Swift 4 \cite{se0148}. It is conceivable that Swift might get generic (computed) properties at some point, or even generic associated types (which would be a major redesign). Beyond that, there are probably limited opportunities for allowing more existing declaration kinds to be generic, but who knows.
\section{Constraint Types}\label{constraints}
\IndexDefinition{constraint type}
\index{requirement}
\IndexDefinition{inheritance clause}
\index{generic parameter declaration}
A generic requirement adds new capabilities to a generic parameter type, by restricting the possible substituted concrete types to those that provide this capability. The next section will introduce the trailing \texttt{where} clause syntax for stating generic requirements in a fully general way. Before doing that, we'll take a look at the simpler mechanism of stating a \emph{constraint type} in the inheritance clause of a generic parameter declaration:
\begin{Verbatim}
func allEqual<T: Equatable>(_ elements: [T]) {...}
\end{Verbatim}
\index{protocol type}%
\index{protocol composition type}%
\index{parameterized protocol type}%
\index{class type}%
\Index{AnyObject@\texttt{AnyObject}}%
\index{layout constraint}%
\Index{Any@\texttt{Any}}%
A constraint type is one of the following:
\begin{enumerate}
\item A protocol type, like \texttt{Hashable}.
\item A parameterized protocol type, like \texttt{Sequence<String>} (Section~\ref{protocols}).
\item A protocol composition, like \texttt{ShapeProtocol \& MyClass}. Protocol compositions were originally just compositions of protocol types, but they can include class types as of Swift 4 \cite{se0156}.
\item A class type, like \texttt{NSObject}.
\item The \texttt{AnyObject} \emph{layout constraint}, which restricts the possible concrete types to those represented as a single reference-counted pointer.
\item The empty protocol composition, written \texttt{Any}. Writing \texttt{Any} in a generic parameter's inheritance clause is pointless, but it is allowed for completeness.
\end{enumerate}
Constraint types can appear in various positions:
\begin{enumerate}
\item In the inheritance clause of a generic parameter declaration, which is the focus of this section.
\item On the right hand side of a conformance, superclass or layout requirement in a \texttt{where} clause, which you will see shortly.
\item In the inheritance clauses of protocols and associated types (Section~\ref{protocols}).
\item Following the \texttt{some} keyword in an opaque parameter (Section~\ref{opaque parameters}) or return type (Chapter~\ref{opaqueresult}).
\item Following the \texttt{any} keyword in an existential type (Chapter~\ref{existentialtypes}). A single class type cannot be the constraint type of an existential; \texttt{any~NSObject} is just written as \texttt{NSObject}. Existential types where the constraint type is \texttt{AnyObject} and \texttt{Any} can also be written without the \texttt{any} keyword.
\end{enumerate}
\begin{example}
In Listing~\ref{dependentconstrainttype}, the generic parameter \texttt{B} of \texttt{open(box:)} references the generic parameter \texttt{C} from its constraint type; the lexical scope of \texttt{C} includes its own generic parameter list.
\end{example}
\begin{listing}\captionabove{The constraint type of \texttt{B} in \texttt{open(box:)} refers to \texttt{C}}\label{dependentconstrainttype}
\begin{Verbatim}
class Box<Contents> {
var contents: Contents
}
func open<B: Box<C>, C>(box: B) -> C {
return box.contents
}
struct Vegetables {}
class FarmBox: Box<Vegetables> {}
let vegetables: Vegetables = open(box: FarmBox())
\end{Verbatim}
\end{listing}
\section{Requirements}\label{trailing where clauses}
\IndexDefinition{where clause@\texttt{where} clause}
\index{trailing where clause@trailing \texttt{where} clause|see{\texttt{where} clause}}
\IndexDefinition{requirement representation}
\IndexDefinition{constraint requirement representation}
\IndexDefinition{same-type requirement representation}
\IndexDefinition{requirement}
A constraint type in the inheritance clause of a generic parameter declaration is sugar for a \texttt{where} clause requirement whose subject type is the generic parameter type:
\begin{Verbatim}
struct Set<Element: Hashable> {...}
struct Set<Element> where Element: Hashable {...}
\end{Verbatim}
The requirements in a \texttt{where} clause name the subject type explicitly, so that dependent member types can be constrained too, for example:
\begin{Verbatim}
func isSorted<S: Sequence>(_: S) where S.Element: Comparable {...}
\end{Verbatim}
Another generalization over generic parameter inheritance clauses is that \texttt{where} clauses can define same-type requirements:
\begin{Verbatim}
func merge<S: Sequence, T: Sequence>(_: S, _: T) -> [S.Element]
where S: Comparable, S.Element == T.Element {...}
\end{Verbatim}
Formally, a \texttt{where} clause is a list of one or more \emph{requirement representations}. There are three kinds of requirement representations, with the first two kinds storing a pair of type representations, and the third storing a type representation and layout constraint:
\begin{enumerate}
\item \textbf{Constraint requirement representations}, written as \texttt{T:\ C}, where \texttt{T} and \texttt{C} are type representations, called the subject type and constraint type, respectively.
\item \textbf{Same-type requirement representations}, written as \texttt{T == U}, where \texttt{T} and \texttt{U} are type representations.
\item \textbf{Layout requirement representations}, written as \texttt{T:\ L} where \texttt{L} is a layout constraint. The only type of layout constraint which can be written in the source language is \texttt{AnyObject}, but this is actually parsed as a constraint requirement representation. Bona-fide layout requirement representations only appear within the \texttt{@\_specialize} attribute.
\end{enumerate}
\index{requirement resolution}
Just as type resolution resolves type representations to types, \emph{requirement resolution} resolves requirement representations to \emph{requirements}. Requirements store types instead of type representations. Figure~\ref{typerequirementrepresentation} shows the correspondence.
\begin{figure}\captionabove{Types and requirements, at the syntactic and semantic layers}\label{typerequirementrepresentation}
\begin{center}
\begin{tikzcd}[column sep=3cm,row sep=1cm]
\mathboxed{requirement representation} \arrow[d, "\text{contains}"{left}] \arrow[r, "\text{resolves to}"] &\mathboxed{requirement} \arrow[d, "\text{contains}"] \\
\mathboxed{type representation} \arrow[r, "\text{resolves to}"]&\mathboxed{type}
\end{tikzcd}
\end{center}
\end{figure}
\IndexDefinition{conformance requirement}%
\IndexDefinition{superclass requirement}%
\IndexDefinition{layout requirement}%
\IndexDefinition{same-type requirement}%
\IndexDefinition{requirement kind}%
Requirement resolution resolves each type representation to a type, and computes the requirement kind. The requirement kind encodes more detail than the requirement representation kind:
\begin{itemize}
\item \textbf{Conformance requirements} state that a type must conform to a protocol, protocol composition or parameterized protocol type.
\item \textbf{Superclass requirements} state that a type must either equal to be a subclass of the superclass type.
\item \textbf{Layout requirements} state that a type must satisfy a layout constraint.
\item \textbf{Same-type requirements} state that two interface types are equivalent under the \index{reduced type equality}\index{equivalent type parameter|see{reduced type equality}}reduced type equality relation (this concept was first introduced in Chapter~\ref{types} and will be detailed in Section~\ref{reducedtypes}).
\end{itemize}
Constraint requirement representations resolve to conformance, superclass and layout requirements; the exact kind of requirement is only known after type resolution resolves the constraint type by performing name lookups. Same-type requirement representations always resolve to same-type requirements.
The simpler syntax introduced in the previous section, where a constraint type can be written in the inheritance clause of a generic parameter declaration, also resolves to a requirement. The requirement's subject type is the generic parameter type. The requirement kind is always a conformance, superclass or layout requirement, never a same-type requirement.
\paragraph{History}
The \texttt{where} clause syntax used to be part of the generic parameter list itself, but was moved to the modern \Index{where clause@\texttt{where} clause}``trailing'' form in Swift 3 \cite{se0081}. Implementation limitations prevented \texttt{where} clause requirements from constraining outer generic parameters until Swift 3. Once these implementation difficulties were solved, it no longer made sense to restrict a \texttt{where} clause to appear only on a declaration that has its own generic parameter list; this restriction was lifted in Swift 5.3 \cite{se0261}, allowing any declaration in a generic context to declare a \texttt{where} clause.
For example, the following became valid:
\begin{Verbatim}
enum LinkedList<Element> {
...
func sum() -> Element where Element: AdditiveArithmetic {...}
}
\end{Verbatim}
There is no semantic distinction between attaching a \texttt{where} clause to a member of a type, or moving the member to a constrained extension, so the above is equivalent to the following:
\begin{Verbatim}
extension LinkedList where Element: AdditiveArithmetic {
func sum() -> Element {...}
}
\end{Verbatim}
\index{mangling}
Unfortunately, due to historical quirks in the name mangling scheme, the above is not an \index{ABI}ABI-compatible transformation.
\index{value requirement}
\index{conforming type}
\paragraph{Protocol requirements}
There is still one situation where constraining outer generic parameters is prohibited, for usability reasons. The \emph{value requirements} of a protocol (properties, subscripts and methods) cannot constrain \texttt{Self} or its associated types in their \Index{where clause@\texttt{where} clause}\texttt{where} clause. Since value requirements must be fulfilled by all concrete conforming types, if a value requirement's \texttt{where} clause imposed additional constraints on \texttt{Self}, it would be impossible for a concrete type which did not otherwise satisfy those constraints to declare a witness for this value requirement. Rather than allow defining a protocol which cannot be conformed to, the type checker diagnoses an error.
\begin{example}
The following protocol attempts to define an \texttt{Element} associated type with no requirements, and a \texttt{minElement()} method which requires that \texttt{Element} conform to the \texttt{Comparable} protocol:
\begin{Verbatim}
protocol SetProtocol {
associatedtype Element
func minElement() -> Element where Element: Comparable
}
\end{Verbatim}
This is not allowed, because there is no way to implement the \texttt{minElement()} requirement in a concrete conforming type whose \texttt{Element} type is not \texttt{Comparable}. One way to fix the error is to move the \texttt{where} clause from the protocol method to the associated type, which would instead impose the requirement on all conforming types.\end{example}
\section{Opaque Parameters}\label{opaque parameters}
\index{opaque parameter}
\index{depth}
\index{index}
\index{parsed generic parameter list}
In the type of a function or subscript parameter, the \texttt{some} keyword declares an \emph{opaque parameter type}. The \texttt{some} keyword is followed by a constraint type. This introduces an unnamed generic parameter, and the constraint type imposes a conformance, superclass or layout requirement on this generic parameter. When a declaration has both a parsed generic parameter list and opaque parameters, the opaque parameters have the same depth as the parsed generic parameters, and appear after the parsed generic parameters in index order.
\index{expression}
Opaque parameter types are unnamed, and therefore are not visible to type resolution. In particular, there is no way to refer to an opaque parameter type within the function's \Index{where clause@\texttt{where} clause}\texttt{where} clause, or from a type annotation on a declaration nested in the function's body. From expression context however, the type of an opaque parameter can be obtained via the built-in \texttt{type(of:)} pseudo-function,\footnote{It looks like a function call, but the type checking behavior of \texttt{type(of:)} cannot be described by a Swift function type; it is not a real function.} which produces a metatype value. This allows for invoking static methods and such.
\begin{example}
These two definitions are equivalent:
\begin{Verbatim}
func merge<E>(_: some Sequence<E>, _: some Sequence<E>) -> [E] {}
func merge<E, S: Sequence<E>, T: Sequence<E>>(_: S, _: T) -> [E] {}
\end{Verbatim}
The constraint types here are parameterized protocol types, which are described in the next section.
\end{example}
Opaque parameter declarations were introduced in Swift 5.7 \cite{se0341}. Note that \texttt{some} appearing in the return type of a function declares an \emph{opaque return type}, which is a related but quite different feature (Chapter~\ref{opaqueresult}).
\section{Protocol Declarations}\label{protocols}
\index{protocol declaration}
\index{conforming type}
\IndexDefinition{protocol Self type@protocol \texttt{Self} type}
Protocols have an implicit generic parameter list with a single generic parameter named \texttt{Self}, which represents the conforming type of a concrete conformance. Protocols can impose \IndexDefinition{associated requirement}\emph{associated requirements} on the \texttt{Self} type and its member types, and any concrete conformance to this protocol must satisfy those requirements. The associated requirements are collected in the protocol's requirement signature (Section~\ref{requirement sig}). Protocols can only appear at the top level of a source file, and structs, classes and enums cannot be nested inside protocols (Section~\ref{nested nominal types}).
\IndexDefinition{primary associated type}%
\index{parameterized protocol type}%
\paragraph{Primary associated types}
A protocol can declare a list of \emph{primary associated types} with a syntax resembling a generic parameter list. While generic parameter lists introduce new generic parameter declarations, the entries in the primary associated type list reference \emph{existing} associated types declared in the protocol's body.
A protocol with primary associated types can then be used as a parameterized protocol type. As a constraint type, a parameterized protocol type is equivalent to a conformance requirement between the subject type and the protocol, together with same-type requirements. The same-type requirements relate the primary associated types of the subject type with the arguments of the parameterized protocol type.
\begin{example}
The standard library's iterator protocol has a primary associated type:
\begin{Verbatim}
protocol IteratorProtocol<Element> {
associatedtype Element
mutating func next() -> Element?
}
\end{Verbatim}
We can then write a parameterized protocol type:
\begin{Verbatim}
func sumOfSquares<I: IteratorProtocol<Int>>(_: I) -> Int {...}
\end{Verbatim}
The above is equivalent to the following \emph{desugaring}, which will receive a more formal treatment in Section~\ref{requirement desugaring}:
\begin{Verbatim}
func sumOfSquares<I: IteratorProtocol>(_: I) -> Int
where I.Element == Int {...}
\end{Verbatim}
\end{example}
Parameterized protocol types and primary associated types were added to the language in Swift~5.7~\cite{se0346}.
\index{associated type declaration}%
\Index{where clause@\texttt{where} clause}%
\index{inheritance clause}%
\paragraph{Associated type requirements}
Associated types can state one or more constraint types in their inheritance clause, in addition to an optional \texttt{where} clause. Constraint types in the inheritance clause resolve to requirements whose subject type is the associated type declaration's declared interface type---which you might recall is the dependent member type \texttt{Self.[P]A}, where \texttt{A} is the associated type declaration and \texttt{P} is the protocol. The standard library \texttt{Sequence} protocol demonstrates all of these features:
\begin{Verbatim}
protocol Sequence<Element> {
associatedtype Iterator: IteratorProtocol
associatedtype Element where Iterator.Element == Element
func makeIterator() -> Iterator
}
\end{Verbatim}
The conformance requirement on \texttt{Iterator} could have been written with a \texttt{where} clause as well:
\begin{Verbatim}
associatedtype Iterator where Iterator: IteratorProtocol
\end{Verbatim}
Finally, a \texttt{where} clause can be attached to the protocol itself; there is no semantic difference between that and attaching it to an associated type:
\begin{Verbatim}
protocol Sequence where Iterator: IteratorProtocol,
Iterator.Element == Element {...}
\end{Verbatim}
Unlike generic parameters, associated type inheritance clauses allow multiple entries, separated by commas. This is effectively equivalent to a single inheritance clause entry containing a protocol composition:
\begin{Verbatim}
associatedtype Data: Codable & Hashable
associatedtype Data: Codable, Hashable
\end{Verbatim}
\paragraph{Unqualified lookup inside protocols}
Within the entire source range of the protocol declaration, unqualified references to associated types, like \texttt{Element} and \texttt{Iterator} above, resolve to their declared interface type. This is a shorthand for accessing the associated type as a member type of the protocol \texttt{Self} type. The \texttt{Sequence} protocol above could instead have been declared as follows:
\begin{Verbatim}
protocol Sequence where Self.Iterator: IteratorProtocol,
Self.Iterator.Element == Self.Element {...}
\end{Verbatim}
\index{inheritance clause}
\IndexDefinition{inherited protocol}
\index{protocol inheritance|see{inherited protocol}}
\index{conforming type}
\paragraph{Protocol inheritance clauses}
Constraint types appearing in the protocol's inheritance clause become generic requirements on \texttt{Self} in the same manner that constraint types in generic parameter inheritance clauses become requirements on the generic parameter type. Requirements on \texttt{Self} are imposed by the conformance checker on concrete types conforming to the protocol.
If the constraint type is another protocol, we call the protocol stating the requirement the \emph{derived protocol} and the protocol named by the constraint type the \emph{base protocol}. The derived protocol is said to \emph{inherit} from (or sometimes, \emph{refine}) the base protocol. Protocol inheritance can be observed in two ways; first, every concrete type conforming to the derived protocol must also conform to the base protocol. Second, qualified name lookup will search through inherited protocols when the lookup begins from the derived protocol or one of its concrete conforming types.
For example, the standard library's \texttt{Collection} protocol inherits from \texttt{Sequence}, therefore any concrete type conforming \texttt{Collection} must also conform to \texttt{Sequence}. If some type parameter \texttt{T} is known to conform to \texttt{Collection}, members of both the \texttt{Collection} and \texttt{Sequence} protocols will be visible to qualified name lookup on a value of type \texttt{T}.
\begin{Verbatim}
protocol Collection: Sequence {...}
\end{Verbatim}
Protocols can restrict their conforming types to those with a reference-counted pointer representation by stating an \texttt{AnyObject} layout constraint:
\begin{Verbatim}
protocol BoxProtocol: AnyObject {...}
\end{Verbatim}
Protocols can also impose a superclass requirement on their conforming types:
\begin{Verbatim}
class Plant {}
class Animal {}
protocol Duck: Animal {}
class MockDuck: Plant, Duck {}
// error: MockDuck is not a subclass of Animal
\end{Verbatim}
\IndexDefinition{class-constrained protocol}
A protocol is \emph{class-constrained} if the \texttt{Self:~AnyObject} requirement can be proven from its inheritance clause; either directly stated, implied by a superclass requirement, or inherited from another protocol. Qualified name lookup understands a superclass in a protocol's inheritance clause, making the members of the superclass visible to all lookups that look into the protocol.
We'll say more about the semantics of protocol inheritance clauses and name lookup in Section \ref{requirement sig}~and~\ref{identtyperepr}.
\paragraph{History}
In older releases of Swift, protocols could only constrain associated types by writing a constraint type in the associated type's inheritance clause, which limited the kinds of requirements that could be imposed on the associated type. The trailing \texttt{where} clause syntax was extended to cover associated types and protocols in Swift~4~\cite{se0142}.
\index{recursive conformance requirement}%
Another important generalization allowed an associated type to conform to the same protocol that it appears in, either directly or indirectly. The ability to declare a so-called \emph{recursive conformance} was introduced in Swift 4.1 \cite{se0157}. This feature has some profound implications, which are further explored in Section~\ref{type parameter graph}, \ref{recursive conformances}, \ref{monoidsasprotocols}, and \ref{recursive conformances redux}.
\section{Source Code Reference}\label{genericdeclsourceref}
Key source files:
\begin{itemize}
\item \SourceFile{include/swift/AST/Decl.h}
\item \SourceFile{include/swift/AST/DeclContext.h}
\item \SourceFile{include/swift/AST/GenericParamList.h}
\item \SourceFile{lib/AST/Decl.cpp}
\item \SourceFile{lib/AST/DeclContext.cpp}
\item \SourceFile{lib/AST/GenericParamList.cpp}
\end{itemize}
Other source files:
\begin{itemize}
\item \SourceFile{include/swift/AST/Types.h}
\item \SourceFile{lib/AST/NameLookup.cpp}
\end{itemize}
\index{declaration context}
\IndexSource{generic context}
\IndexSource{generic declaration}
\IndexSource{parsed generic parameter list}
\apiref{DeclContext}{class}
See also Section~\ref{name lookup}, Section~\ref{declarationssourceref} and Section~\ref{genericsigsourceref}.
\begin{itemize}
\item \texttt{isGenericContext()} answers if this declaration context or one of its parent contexts has a generic parameter list.
\item \texttt{isInnermostContextGeneric()} answers if this declaration context is a generic context with its own generic parameter list, that is, if its declaration is a generic declaration.
\end{itemize}
\apiref{GenericContext}{class}
Base class for declarations which can be generic. See also Section~\ref{genericsigsourceref}.
\begin{itemize}
\item \texttt{getParsedGenericParams()} returns the declaration's parsed generic parameter list, or \texttt{nullptr}.
\item \texttt{getGenericParams()} returns the declaration's full generic parameter list, which includes any implicit generic parameters. Evaluates a \texttt{GenericParamListRequest}.
\item \texttt{isGeneric()} answers if this declaration has a generic parameter list.
\item \texttt{getGenericContextDepth()} returns the depth of the innermost generic parameter list, or \texttt{(unsigned)-1} if neither this declaration nor any outer declaration is generic.
\item \texttt{getTrailingWhereClause()} returns the trailing \texttt{where} clause, or \texttt{nullptr}.
\end{itemize}
Trailing \texttt{where} clauses are not preserved in serialized generic contexts. Most code uses \texttt{GenericContext::getGenericSignature()} instead (Section~\ref{genericsigsourceref}), except when actually building the generic signature.
\IndexSource{generic parameter list}
\apiref{GenericParamList}{class}
A generic parameter list.
\begin{itemize}
\item \texttt{getParams()} returns an array of generic parameter declarations.
\item \texttt{getOuterParameters()} returns the outer generic parameter list, linking multiple generic parameter lists for the same generic context. Only used for extensions of nested generic types.
\end{itemize}
\IndexSource{protocol Self type@protocol \texttt{Self} type}
\apiref{GenericParamListRequest}{class}
This request creates the full generic parameter list for a declaration. Kicked off from \texttt{GenericContext::getGenericParams()}.
\begin{itemize}
\item For protocols, this creates the implicit \texttt{Self} parameter.
\item For functions and subscripts, calls \texttt{createOpaqueParameterGenericParams()} to walk the formal parameter list and look for \texttt{OpaqueTypeRepr}s.
\item For extensions, calls \texttt{createExtensionGenericParams()} which clones the generic parameter lists of the extended nominal itself and all of its outer generic contexts, and links them together via \texttt{GenericParamList::getOuterParameters()}.
\end{itemize}
\IndexSource{generic parameter declaration}
\apiref{GenericTypeParamDecl}{class}
A generic parameter declaration.
\begin{itemize}
\item \texttt{getDepth()} returns the depth of the generic parameter declaration.
\item \texttt{getIndex()} returns the index of the generic parameter declaration.
\item \texttt{getName()} returns the name of the generic parameter declaration.
\item \texttt{getDeclaredInterfaceType()} returns the non-canonical generic parameter type for this declaration.
\item \texttt{isOpaque()} answers if this generic parameter is associated with an opaque parameter.
\item \texttt{getOpaqueTypeRepr()} returns the associated \texttt{OpaqueReturnTypeRepr} if this is an opaque parameter, otherwise \texttt{nullptr}.
\item \texttt{getInherited()} returns the generic parameter declaration's inheritance clause.
\end{itemize}
Inheritance clauses are not preserved in serialized generic parameter declarations. Requirements stated on generic parameter declarations are part of the corresponding generic context's generic signature, so except when actually building the generic signature, most code uses \texttt{GenericContext::getGenericSignature()} instead (Section~\ref{genericsigsourceref}).
\IndexSource{generic parameter type}
\IndexSource{depth}
\IndexSource{index}
\apiref{GenericTypeParamType}{class}
A generic parameter type.
\begin{itemize}
\item \texttt{getDepth()} returns the depth of the generic parameter declaration.
\item \texttt{getIndex()} returns the index of the generic parameter declaration.
\item \texttt{getName()} returns the name of the generic parameter declaration, only if this is a non-canonical type.
\end{itemize}
\IndexSource{where clause@\texttt{where} clause}
\apiref{TrailingWhereClause}{class}
The syntactic representation of a trailing \texttt{where} clause.
\begin{itemize}
\item \texttt{getRequirements()} returns an array of \texttt{RequirementRepr}.
\end{itemize}
\IndexSource{requirement representation}
\apiref{RequirementRepr}{class}
The syntactic representation of a requirement in a trailing \texttt{where} clause.
\begin{itemize}
\item \texttt{getKind()} returns a \texttt{RequirementReprKind}.
\item \texttt{getFirstTypeRepr()} returns the first \texttt{TypeRepr} of a same-type requirement.
\item \texttt{getSecondTypeRepr()} returns the second \texttt{TypeRepr} of a same-type requirement.
\item \texttt{getSubjectTypeRepr()} returns the first \texttt{TypeRepr} of a constraint or layout requirement.
\item \texttt{getConstraintTypeRepr()} returns the second \texttt{TypeRepr} of a constraint requirement.
\item \texttt{getLayoutConstraint()} returns the layout constraint of a layout requirement.
\end{itemize}
\apiref{RequirementReprKind}{enum class}
\begin{itemize}
\item \texttt{RequirementRepr::TypeConstraint}
\item \texttt{RequirementRepr::SameType}
\item \texttt{RequirementRepr::LayoutConstraint}
\end{itemize}
\apiref{WhereClauseOwner}{class}
Represents a reference to some set of requirement representations which can be resolved to requirements, for example a trailing \texttt{where} clause. This is used by various requests, such as the \texttt{RequirementRequest} below, and the \texttt{InferredGenericSignatureRequest} in Section~\ref{buildinggensigsourceref}.
\begin{itemize}
\item \texttt{getRequirements()} returns an array of \texttt{RequirementRepr}.
\item \texttt{visitRequirements()} resolves each requirement representation and invokes a callback with the \texttt{RequirementRepr} and resolved \texttt{Requirement}.
\end{itemize}
\apiref{RequirementRequest}{class}
Request which can be evaluated to resolve a single requirement representation in a \texttt{WhereClauseOwner}. Used by \texttt{WhereClauseOwner::visitRequirements()}.
\IndexSource{protocol declaration}
\IndexSource{primary associated type}
\apiref{ProtocolDecl}{class}
A protocol declaration.
\begin{itemize}
\item \texttt{getTrailingWhereClause()} returns the protocol \texttt{where} clause, or \texttt{nullptr}.
\item \texttt{getAssociatedTypes()} returns an array of all associated type declarations in the protocol.
\item \texttt{getPrimaryAssociatedTypes()} returns an array of all primary associated type declarations in the protocol.
\item \texttt{getInherited()} returns the parsed inheritance clause.
\end{itemize}
Trailing \texttt{where} clauses and inheritance clauses are not preserved in serialized protocol declarations. Except when actually building the requirement signature, most code uses \texttt{ProtocolDecl::getRequirementSignature()} instead (Section~\ref{genericsigsourceref}).
\IndexSource{inherited protocol}
The last four utility methods operate on the requirement signature, so are safe to use on deserialized protocols:
\begin{itemize}
\item \texttt{getInheritedProtocols()} returns an array of all protocols directly inherited by this protocol, computed from the inheritance clause.
\item \texttt{inheritsFrom()} determines if this protocol inherits from the given protocol, possibly transitively.
\item \texttt{getSuperclass()} returns the protocol's superclass type.
\item \texttt{getSuperclassDecl()} returns the protocol's superclass declaration.
\end{itemize}
\index{associated type declaration}
\apiref{AssociatedTypeDecl}{class}
An associated type declaration.
\begin{itemize}
\item \texttt{getTrailingWhereClause()} returns the associated type's trailing \texttt{where} clause, or \texttt{nullptr}.
\item \texttt{getInherited()} returns the associated type's inheritance clause.
\end{itemize}
Trailing \texttt{where} clauses and inheritance clauses are not preserved in serialized associated type declarations. Requirements on associated types are part of a protocol's requirement signature, so except when actually building the requirement signature, most code uses \texttt{ProtocolDecl::getRequirementSignature()} instead (Section~\ref{genericsigsourceref}).
\end{document}
|