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 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
|
\documentclass[../generics]{subfiles}
\begin{document}
\chapter{Declarations}\label{decls}
\lettrine{D}{eclarations} are the \IndexDefinition{declaration}building blocks of Swift programs. In \ChapRef{compilation model}, we started by viewing the user's program as a series of \index{module declaration}module declarations, where a module declaration holds \index{file unit}file units. A file unit further holds a list of \IndexDefinition{top-level declaration}top-level declarations, which correspond to the main divisions in a source file. The different kinds of declarations are categorized into a taxonomy, and we will survey this taxonomy, as we did with types in \ChapRef{types}. Our principal goal will be describing the syntactic representations for declaring generic parameters and stating requirements, which are common to all generic declarations; once we have that, we can proceed to \PartRef{part semantics}.
We begin with two major divisions in the declaration taxonomy:
\begin{enumerate}
\item A \IndexDefinition{value declaration}\emph{value declaration} is a one that can be referenced by name from an \index{expression}expression; this includes variables, functions, and such. Every value declaration has an \IndexDefinition{interface type!value declaration}\emph{interface type}, which is the type assigned to an expression that names this declaration.
\item A \IndexDefinition{type declaration}\emph{type declaration} is one that can be referenced by name from within a \index{type representation}type representation. This includes structs, type aliases, and so on. A type declaration declares a type, called the \IndexDefinition{declared interface type}\emph{declared interface type} of the type declaration.
\end{enumerate}
Not all declarations are value declarations. An \index{extension declaration}extension declaration adds members to an existing nominal type declaration, as we'll see in \ChapRef{extensions}, but an extension does not itself have a name. A \IndexDefinition{top-level code declaration}\emph{top-level code declaration} holds the statements and expressions written at the top level of a source file, and again, it does not have a name, semantically.
\paragraph{Declaration contexts.} Every declaration is contained in a \IndexDefinition{declaration context}\emph{declaration context}, and a declaration context is anything that \emph{contains} declarations. Consider this program:
\begin{Verbatim}
func squares(_ nums: [Int]) -> [Int] {
return nums.map { x in x * x }
}
\end{Verbatim}
The \index{parameter declaration}parameter declaration ``\texttt{x}'' is a child of the closure expression ``\verb|{ x in x * x }|'', and not a direct child of the enclosing function declaration. So a \index{closure expression}closure expression is a declaration context, but not a declaration. On the other hand, a parameter declaration is a declaration, but not a declaration context. Finally, the \texttt{squares()} function itself is both a declaration, and a declaration context.
\paragraph{Type declarations.} Types can be written inside expressions, so every type declaration is also a value declaration. We can understand the relationship between the interface type and declared interface type of a type declaration by looking at this example:
\begin{Verbatim}
struct Horse {}
let myHorse: Horse = Horse()
\end{Verbatim}
The struct declaration \index{horse}\texttt{Horse} is referenced twice, first in the type representation on the left-hand side of ``\texttt{=}'' and then again in the \index{expression}\index{initial value expression}initial value expression on the right. On the left-hand side, it's referenced as a type declaration; we want the \emph{declared interface type}, which is the nominal type \texttt{Horse}, because this type's values are stored inside the \texttt{myHorse} variable. The second reference to \texttt{Horse}, within the \index{call expression}call expression, refers to the \emph{type itself} as a value declaration, so we want the \emph{interface type}, which is the \index{metatype type}metatype \texttt{Horse.Type}. (Recall the diagram from \SecRef{more types}.) When a metatype is the callee in a call expression, we interpret it as looking up the member named \texttt{init}:
\begin{Verbatim}
struct Horse {}
let myHorseType: Horse.Type = Horse.self
let myHorse: Horse = myHorseType.init()
\end{Verbatim}
The interface type of a type declaration always wraps its declared interface type in a metatype type. (It sounds like a mouthful, but the idea is simple.)
\paragraph{Nominal type declarations.}
\IndexDefinition{nominal type declaration}Introduced with the \texttt{struct}, \IndexDefinition{enum declaration}\texttt{enum} and \IndexDefinition{class declaration}\texttt{class} keywords; \IndexSwift{5.5}Swift~5.5 also added \texttt{actor}, which to us is just a class~\cite{se0306}. Nominal type declarations are declaration contexts, and the declarations they contain are called their \IndexDefinition{member declaration}\emph{member declarations}. If a member declaration is a function, we call it a \IndexDefinition{method declaration}\emph{method}, a member variable is a \IndexDefinition{property declaration}\emph{property}, and a \IndexDefinition{member type declaration}\emph{member type declaration} is exactly that.
Structs and classes can contain a special kind of property declaration called a \IndexDefinition{stored property declaration}\emph{stored property declaration}. Struct values directly store their stored properties, while a class value is a reference to a heap allocated \index{boxing}box. Enum values store exactly one element among several; enum declarations instead contain \IndexDefinition{enum element declaration}\emph{enum element declarations}, introduced with the \texttt{case} keyword.
The members of a nominal type declaration are visible to name lookup (\SecRef{name lookup}), both in the nominal type declaration's scope (unqualified lookup) and outside (qualified lookup). \ListingRef{unqualified lookup listing} shows three features we will cover in detail later:
\begin{itemize}
\item Nominal type declarations can conform to protocols (\ChapRef{conformances}).
\item Extensions add members to existing nominal type declarations (\ChapRef{extensions}).
\item A class can inherit from a \index{superclass type}superclass type, and members of the superclass are also visible from the subclass (\SecRef{classinheritance}).
\end{itemize}
\begin{listing}\captionabove{Some behaviors of name lookup}\label{unqualified lookup listing}
\begin{Verbatim}
class Form { static func callee1() {} }
protocol Shape { static func callee2() }
extension Shape { static func callee3() {} }
struct Square: Shape {
class Circle: Form {
static func caller() {
... // unqualified lookup from here
}
}
}
\end{Verbatim}
\end{listing}
The body of \texttt{caller()} can reference \texttt{callee1()}, \texttt{callee2()} or \texttt{callee3()} with a single identifier. To resolve the identifier, unqualified lookup must search through these declaration contexts, starting in the top-left corner:
\begin{center}
\begin{tikzpicture}[x=4.5cm,y=1.5cm]
\node (caller) [class,anchor=mid] at (0,2) {\texttt{\vphantom{p}func caller()}};
\node (Circle) [class,anchor=mid] at (1,2) {\texttt{\vphantom{p}class Circle}};
\node (Square) [class,anchor=mid] at (2,2) {\texttt{struct Square}};
\node (Form) [class,anchor=mid] at (1,1) {\texttt{\vphantom{p}class Form}};
\node (Shape) [class,anchor=mid] at (2,1) {\texttt{protocol Shape}};
\node (extShape) [class,anchor=mid] at (2,0) {\texttt{extension Shape}};
\path [arrow] (caller) edge [above] node {\footnotesize{parent}} (Circle);
\path [arrow] (Circle) edge [above] node {\footnotesize{parent}} (Square);
\path [arrow] (Square) edge [right] node {\footnotesize{conforms to}} (Shape);
\path [arrow] (Circle) edge [right] node {\footnotesize{superclass}} (Form);
\draw [arrow] (Shape) edge [right] node {\footnotesize{extension}} (extShape);
\end{tikzpicture}
\end{center}
We will say more about name lookup in \ChapRef{typeresolution} and \SecRef{direct lookup}.
A nominal type declaration declares a new type with its own name and identity (hence ``nominal''). The declared interface type of a nominal type declaration is called a \index{nominal type}nominal type, which we talked about in \SecRef{fundamental types}:
\begin{Verbatim}
struct Universe { // declared interface type: Universe
struct Galaxy {} // declared interface type: Universe.Galaxy
func solarSystem() {
struct Planet() // declared interface type: Planet
}
}
\end{Verbatim}
The declared interface type of the \texttt{Galaxy} struct is \texttt{Universe.Galaxy}, while the declared interface type of \texttt{Planet} is just \texttt{Planet}, with no parent type. This reflects the semantic difference; \texttt{Galaxy} is visible to qualified lookup as a member of \texttt{Universe}, while \texttt{Planet} is only visible to unqualified lookup within the scope of \texttt{solarSystem()}; we call it a \IndexDefinition{local type declaration}\emph{local type declaration}. \SecRef{nested nominal types} gives more detail about nominal type nesting.
\paragraph{Type alias declarations.} These are introduced by the \IndexDefinition{type alias declaration}\texttt{typealias} keyword. The \IndexDefinition{underlying type}underlying type is written on the right-hand side of ``\texttt{=}'':
\begin{Verbatim}
typealias Hands = Int // one hand is four inches
func measure(horse: Horse) -> Hands {...}
let metatype = Hands.self
\end{Verbatim}
The declared interface type of a type alias declaration is a \index{type alias type}type alias type. The canonical type of this type alias type is just the underlying type. Therefore, if we print the return type of \texttt{measure()} in a diagnostic message, we will print it as ``\texttt{Hands}'', but otherwise it behaves as if it were an \texttt{Int}.
As with all type declarations, the interface type of a type alias declaration is the metatype of its declared interface type. In the above, the expression ``\texttt{Hands.self}'' has the metatype type \texttt{Hands.Type}. This is a sugared type, canonically equal to \texttt{Int.Type}.
While type aliases are declaration contexts, the only declarations a type alias can contain are generic parameter declarations, in the event the type alias is generic.
\paragraph{Other type declarations.}
We've now seen the first two kinds of type declarations. In the next two sections, we expand on this by looking at the declarations of generic parameters, protocols and associated types. At this point, our foray into Swift generics can begin in earnest. Here are all the type declaration kinds and their declared interface types, with a representative specimen of each:
\begin{center}
\begin{tabular}{ll}
\toprule
\textbf{Type declaration}&\textbf{Declared interface type}\\
\midrule
Nominal type declaration:&Nominal type:\\
\verb|struct Horse {...}|&\verb|Horse|\\
\midrule
Type alias declaration:&Type alias type:\\
\verb|typealias Hands = Int|&\verb|Hands|\\
\midrule
Generic parameter declaration:&Generic parameter type:\\
\verb|<T: Sequence>|&\verb|T| (or \rT)\\
\midrule
Protocol declaration:&Protocol type:\\
\verb|protocol Sequence {...}|&\verb|Sequence|\\
\midrule
Associated type declaration:&Dependent member type:\\
\verb|associatedtype Element|&\verb|Self.Element|\\
\bottomrule
\end{tabular}
\end{center}
\section{Generic Parameters}\label{generic params}
Various kinds of declarations can have a \IndexDefinition{generic parameter list}generic parameter list. We call them \IndexDefinition{generic declaration}\emph{generic declarations}. We start with those where the generic parameter list is written in source: \index{struct declaration}structs, \index{enum declaration}enums, \index{class declaration}classes, \IndexDefinition{generic type alias}type aliases, \index{function declaration}functions and \index{constructor declaration}constructors, and \index{subscript declaration}subscripts. In all cases, a \IndexDefinition{parsed generic parameter list}generic parameter list is denoted in source with the \texttt{<...>} syntax following the name of the declaration:
\begin{Verbatim}
struct Outer<T> {...}
\end{Verbatim}
Each comma-separated element in this list is a \IndexDefinition{generic parameter declaration}\emph{generic parameter declaration}; this is a type declaration that declares a generic parameter type. Generic parameter declarations are visible to unqualified lookup in the entire source range of the parent declaration, the one that has the generic parameter list. When generic declarations nest, each inner generic declaration is effectively parameterized by the generic parameters of its outer declarations.
Any declaration kind that can have a generic parameter list is also a \index{declaration context}declaration context in our taxonomy, because it contains other declarations; namely, its generic parameter declarations. We say that a declaration context is a \IndexDefinition{generic context}\emph{generic context} if at least one parent context has a generic parameter list.
The name of a generic parameter declaration plays no role after \index{unqualified lookup}unqualified lookup. Instead, to each generic parameter declaration, we assign a pair of integers (or more accurately, natural numbers; they're non-negative), the \IndexDefinition{depth}\emph{depth} and the \IndexDefinition{index}\emph{index}:
\begin{itemize}
\item The depth selects a generic parameter list; the generic parameters declared by the outermost generic parameter list are at depth zero, and we increment the depth by one for each nested generic parameter list.
\item The index selects a generic parameter within a generic parameter list; we number sibling generic parameter declarations consecutively starting from zero.
\end{itemize}
Let's write some nested generic declarations inside the \texttt{Outer} struct above. In the following, \texttt{two()} is generic over \tT~and~\tU, while \texttt{four()} is generic over~\tT, \texttt{V}, \texttt{W}~and~\texttt{X}:
\begin{Verbatim}
struct Outer<T> {
func two<U>(u: U) -> T {...}
struct Both<V, W> {
func four<X>() -> X {...}
}
}
\end{Verbatim}
When type resolution resolves the type representation ``\tT'' in the return type of \texttt{two()}, it outputs a generic parameter type that prints as ``\tT'', if it appears in a diagnostic for example. This is a \index{sugared type}sugared type. Every generic parameter type also has a canonical form which only records the depth and index; we denote a canonical generic parameter type by ``\ttgp{d}{i}'', where \texttt{d} is the depth and \texttt{i} is the index. Two generic parameter types are canonically equal if they have the same depth and index. This is sound, because the depth and index unambiguously identify a generic parameter within its lexical scope.
Let's enumerate all generic parameters visible within \texttt{two()},
\begin{center}
\begin{tabular}{rll}
\toprule
\textbf{Name:}&\tT&\tU\\
\midrule
\textbf{Depth:}&0&1\\
\textbf{Index:}&0&0\\
\textbf{Type:}&\ttgp{0}{0}&\ttgp{1}{0}\\
\bottomrule
\end{tabular}
\end{center}
and \texttt{four()},
\begin{center}
\begin{tabular}{rllll}
\toprule
\textbf{Name:}&\tT&\texttt{V}&\texttt{W}&\texttt{X}\\
\midrule
\textbf{Depth:}&0&1&1&2\\
\textbf{Index:}&0&0&1&0\\
\textbf{Type:}&\ttgp{0}{0}&\ttgp{1}{0}&\ttgp{1}{1}&\ttgp{2}{0}\\
\bottomrule
\end{tabular}
\end{center}
The generic parameter~\tU\ of \texttt{two()} has the same \index{declared interface type!generic parameter declaration}declared interface type, \ttgp{1}{0}, as the generic parameter~\tV\ of \texttt{four()}. This is not a problem because the source ranges of their parent declarations, \texttt{two()} and \texttt{Both}, do not intersect.
The numbering by depth can be seen in the \index{declared interface type!nested nominal type}declared interface type of a nested generic nominal type declaration. For example, the declared interface type of \texttt{Outer.Both} is the generic nominal type \texttt{Outer<\ttgp{0}{0}>.Both<\ttgp{1}{0}, \ttgp{1}{1}>}.
\paragraph{Implicit generic parameters.} Sometimes the generic parameter list is not written in source. Every protocol declaration has a generic parameter list with a single generic parameter named \IndexSelf\tSelf\ (\SecRef{protocols}), and every extension declaration has a generic parameter list cloned from that of the extended type (\ChapRef{extensions}). These implicit generic parameters can be referenced by name within their scope, just like the generic parameter declarations in a parsed generic parameter list (\SecRef{identtyperepr}).
Function, constructor and subscript declarations can also declare \IndexDefinition{opaque parameter}\emph{opaque parameters} with the \texttt{some} keyword, possibly in combination with a generic parameter list:
\begin{Verbatim}
func pickElement<E>(_ elts: some Sequence<E>) -> E {...}
\end{Verbatim}
An opaque parameter simultaneously declares a parameter value, a generic parameter type that is the type of the value, and a requirement this type must satisfy. Here, we can refer to ``\texttt{elts}'' from an expression inside the function body, but we cannot name the \emph{type} of ``\texttt{elts}'' in a type representation. From \index{expression}expression context however, the type of an opaque parameter can be obtained via the \texttt{type(of:)} special form, which produces a metatype value. This allows for invoking static methods on these types.
The \IndexDefinition{generic parameter list request}\Request{generic parameter list request} appends the opaque parameters to the parsed generic parameter list, so they follow the parsed generic parameters in index order. In \texttt{pickElement()}, the generic parameter \texttt{E} has canonical type~\rT, while the opaque parameter associated with ``\texttt{elts}'' has canonical type~\rU. Opaque parameter declarations also state a constraint type, which imposes a requirement on this unnamed generic parameter. We will discuss this in the next section. Note that when \texttt{some} appears in the return type of a function, it declares an \emph{opaque return type}, which is a related but different feature (\ChapRef{opaqueresult}).
In \ChapRef{genericsig}, we define the generic signature, which records all visible generic parameters of a declaration, independent of surface syntax.
\section{Requirements}\label{requirements}
The requirements of a generic declaration constrain the generic argument types that can be provided by the caller. This endows the generic declaration's type parameters with new capabilities, so they abstract over the concrete types that satisfy those requirements. We use the following encoding for requirements in the theory and implementation.
\begin{definition}\label{requirement def}
A \IndexDefinition{requirement}\emph{requirement} is a triple consisting of a \emph{requirement kind}, a \IndexDefinition{subject type!of requirement}subject type~\tT\ (usually a \index{type parameter}type parameter), and one final piece of information that depends on the requirement kind:
\begin{itemize}
\item A \IndexDefinition{conformance requirement}\textbf{conformance requirement} $\TP$ states that the replacement type for~\tT\ must conform to~\texttt{P}, which must be a protocol, protocol composition, or parameterized protocol type.
\item A \IndexDefinition{superclass requirement}\textbf{superclass requirement} $\TC$ states that the replacement type for~\tT\ must be a subclass of some \index{class type}class type~\tC.
\item A \IndexDefinition{layout requirement}\textbf{layout requirement} $\TAnyObject$ states that the replacement type for~\tT\ must be represented as a single reference-counted pointer at runtime.
\item A \IndexDefinition{same-type requirement}\textbf{same-type requirement} $\TU$ states that the replacement types for \tT~and~\tU\ must be \index{canonical type equality}canonically equal.
\end{itemize}
\end{definition}
When looking at concrete instances of requirements in a self-contained snippet of code, there is no ambiguity in using the same notation for the first three kinds, because the type referenced by the right-hand side determines the requirement kind. When talking about requirements in the abstract, we will explicitly state that~\texttt{P} is some protocol, or~\tC\ is some class, before talking about $\TP$ or $\TC$.
\paragraph{Constraint types.}
Before we introduce the trailing \texttt{where} clause syntax for stating requirements in a fully general way, let's look at the shorthand of stating a \IndexDefinition{constraint type}\emph{constraint type} in the \IndexDefinition{inheritance clause!generic parameter declaration}inheritance clause of a \index{generic parameter declaration}generic parameter declaration:
\begin{Verbatim}
func allEqual<E: Equatable>(_ elements: [E]) {...}
\end{Verbatim}
The generic parameter declaration~\texttt{E} declares the generic parameter type~\rT, and it also states the constraint type \texttt{Equatable}. This is a protocol declared in the standard library, so the stated requirement is the conformance requirement $\ConfReq{\rT}{Equatable}$. More generally, the constraint type is one of the following:
\begin{enumerate}
\item A \index{protocol type!constraint type}protocol type, like \texttt{Equatable}.
\item A \index{parameterized protocol type!constraint type}parameterized protocol type, like \texttt{Sequence<String>}.
\item A \index{protocol composition type!constraint type}protocol composition type, like \texttt{Sequence \& MyClass}.
\item A \index{class type!constraint type}class type, like \texttt{NSObject}.
\item The \Index{AnyObject@\texttt{AnyObject}}\texttt{AnyObject} \index{layout constraint}\emph{layout constraint}, which restricts the possible concrete types to those represented as a single reference-counted pointer.
\end{enumerate}
In the first three cases, the stated requirement becomes a conformance requirement. Otherwise, it is a superclass or layout requirement. In all cases, the subject type of the requirement is the \index{declared interface type!generic parameter declaration}declared interface type of the generic parameter.
\begin{example}
Notice how the generic parameter \texttt{B} of \texttt{open()} states the constraint type \texttt{Box<C>}, and this refers to the second generic parameter, \tC:
\begin{Verbatim}
func open<B: Box<C>, C>(box: B) -> C {
return box.contents!
}
class Box<Contents> {
var contents: Contents? = nil
}
\end{Verbatim}
This illustrates a property of the \index{scope tree}scope tree: generic parameters are visible in the entire \index{source range}source range of a generic declaration, including in the \index{generic parameter list}generic parameter list itself.
The declaration of \texttt{open()} thus states the superclass requirement $\ConfReq{\rT}{Box<\rU>}$. Here is a possible usage of \texttt{open()}, which we leave unexplained:
\begin{Verbatim}
struct Vegetable {}
class FarmBox: Box<Vegetable> {}
let vegetable: Vegetable = open(box: FarmBox())
\end{Verbatim}
\end{example}
\paragraph{Opaque parameters.}
An opaque parameter declaration is written with a \index{constraint type!opaque parameter}constraint type after the \texttt{some} keyword (\SecRef{generic params}). This specifies a conformance, superclass or layout requirement on the \index{opaque parameter}generic parameter type introduced by the opaque parameter declaration. For example, the following two declarations are equivalent:
\begin{Verbatim}
func pickElement<E>(_ elts: some Sequence<E>) -> E {...}
func pickElement<E, S: Sequence<E>>(_ elts: S) -> E {...}
\end{Verbatim}
We will see later that constraint types also appear in various other positions, and in all cases, they state a requirement with some distinguished subject type:
\begin{enumerate}
\item In the inheritance clause of a protocol or associated type (\SecRef{protocols}).
\item Following the \texttt{some} keyword in return position, where it declares an opaque return type (\ChapRef{opaqueresult}).
\item Following the \texttt{any} keyword that references an existential type (\ChapRef{existentialtypes}), with the exception that the constraint type cannot be a class by itself (for example, we allow ``\verb|any NSObject & Equatable|'', but ``\verb|any NSObject|'' is just ``\texttt{NSObject}'').
\end{enumerate}
\paragraph{Trailing where clauses.} Requirements can also be stated in a \IndexDefinition{where clause@\texttt{where} clause}\index{trailing where clause@trailing \texttt{where} clause|see{\texttt{where} clause}}\texttt{where} clause attached to the generic declaration. This allows generality that cannot be expressed using the inheritance clause of a generic parameter alone.
A \texttt{where} clause entry defines a requirement whose subject type is written explicitly, so that \index{dependent member type!in requirements}dependent member types can be be subject to requirements; here, we state two requirements, $\rTSequence$ and $\ConfReq{\rT.Element}{Comparable}$:
\begin{Verbatim}
func isSorted<S>(_: S) where S: Sequence, S.Element: Comparable {...}
\end{Verbatim}
A \texttt{where} clause can also state a same-type requirement. In the next example, we state two conformance requirements using the inheritance clause syntax, another conformance requirement, and the same-type requirement $\SameReq{\rT.Element}{\rU.Element}$:
\begin{Verbatim}
func merge<S1: Sequence, S2: Sequence>(_: S1, _: S2) -> [S1.Element]
where S1: Comparable, S1.Element == S2.Element {...}
\end{Verbatim}
Note that there is no way to refer to an opaque parameter type within the function's \Index{where clause@\texttt{where} clause!opaque parameter}\texttt{where} clause, but every declaration using opaque parameters can always be rewritten into an equivalent one using named generic parameters, so no generality is lost.
We saw in \ChapRef{types} that when the parser reads a type annotation in the source, it constructs a \index{type representation}type representation, a lower-level syntactic object which must be \index{type resolution}resolved to obtain a \index{type}type. Similarly, requirements have a syntactic form, called a \IndexDefinition{requirement representation}\emph{requirement representation}. The parser constructs requirement representations while reading a \texttt{where} clause. The relationship between the syntactic and semantic entities is shown in this diagram:
\begin{center}
\begin{tikzpicture}[node distance=1cm]
\node (ReqRepr) [data] {Requirement representation};
\node (TypeRepr) [data, below=of ReqRepr] {Type representation};
\node (Req) [data, right=2cm of ReqRepr] {Requirement};
\node (Type) [data, below=of Req] {Type};
\draw [arrow] (ReqRepr) -- (TypeRepr);
\draw [arrow] (Req) -- (Type);
\path [arrow] (ReqRepr) edge [left] node {\footnotesize{contains}} (TypeRepr);
\path [arrow] (Req) edge [right] node {\footnotesize{contains}} (Type);
\path [arrow] (ReqRepr) edge [above] node {\footnotesize{resolves to}} (Req);
\path [arrow] (TypeRepr) edge [below] node {\footnotesize{resolves to}} (Type);
\end{tikzpicture}
\end{center}
There are only two kinds of requirement representations, because the ``\texttt{:}'' form cannot distinguish conformance, superclass and layout requirements until we resolve the type representation on the right-hand side:
\begin{enumerate}
\item A \IndexDefinition{constraint requirement representation}\textbf{constraint requirement representation} ``\texttt{T:\ C}'', where \tT\ and \tC\ are type representations.
\item A \IndexDefinition{same-type requirement representation}\textbf{same-type requirement representation} ``\texttt{T == U}'', where \tT\ and \tU\ are type representations.
\end{enumerate}
Recall that a conformance requirement has a protocol type, protocol composition type, or parameterized protocol type on the right-hand side (\SecRef{fundamental types}). In the case of a protocol composition, we decompose the requirement into simpler requirements, one for each member of the composition. For example, if \texttt{MyClass} is a class, the requirement $\ConfReq{\rT}{Sequence~\&~MyClass}$ splits up as $\rTSequence$ and $\ConfReq{\rT}{MyClass}$, the latter being a superclass requirement. The empty protocol composition, written \Index{Any@\texttt{Any}}\texttt{Any}, is a trivial case; stating a conformance requirement to \texttt{Any} does nothing in a \texttt{where} clause, but it is allowed. Parameterized protocol types also decompose, as we'll see in~\SecRef{protocols}.
In the next section, we will introduce a formal system for derived requirements, where we will assume that only conformance requirements to protocol types remain, and that the subject type of a requirement is always a type parameter, and not an arbitrary type. \SecRef{requirement desugaring} will show how we eliminate these unnecessary forms of generality.
\paragraph{Contextually-generic declarations.} A generic declaration nested inside of another generic declaration can state a \texttt{where} clause, without introducing new generic parameters of its own. This is called a \IndexDefinition{contextually-generic declaration}\emph{contextually-generic declaration}:
\begin{Verbatim}
enum LinkedList<Element> {...}
extension LinkedList {
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 \index{constrained extension}constrained extension (\SecRef{constrained extensions}), so the above is equivalent to the following:
\begin{Verbatim}
extension LinkedList where Element: AdditiveArithmetic {
func sum() -> Element {...}
}
\end{Verbatim}
\index{mangling}
However, for historical reasons, these two declarations have distinct \index{mangling!contextually-generic declaration}mangled symbol names, so the above is not an \index{ABI}ABI-compatible transformation.
\medskip
In \ChapRef{genericsig}, we will see that the generic signature of a declaration records all of its requirements, regardless of they were stated in source.
\paragraph{History.} The syntax described in this section has evolved over time:
\begin{itemize}
\item The \texttt{where} clause used to be written within the ``\texttt{<}'' and ``\texttt{>}'', but was moved to the current \Index{where clause@\texttt{where} clause!history}``trailing'' position in \IndexSwift{3.0}Swift 3 \cite{se0081}.
\item Generic type aliases were introduced in \IndexSwift{3.0}Swift 3 \cite{se0048}.
\item \index{protocol composition type!history}Protocol compositions involving class types were introduced in \IndexSwift{4.0}Swift 4 \cite{se0156}.
\item Generic \index{subscript declaration!history}subscripts were introduced in \IndexSwift{4.0}Swift 4 \cite{se0148}.
\item Implementation limitations prevented the \texttt{where} clause from stating requirements that constrain outer generic parameters until Swift 3, and \index{contextually-generic declaration!history}contextually-generic declarations were not allowed until \IndexSwift{5.3}Swift 5.3 \cite{se0261}.
\item \index{opaque parameter!history}Opaque parameter declarations were introduced in \IndexSwift{5.7}Swift 5.7 \cite{se0341}.
\end{itemize}
\section{Protocols}\label{protocols}
The \texttt{protocol} keyword introduces a \IndexDefinition{protocol declaration}\emph{protocol declaration}, which is a special kind of nominal type declaration. The members of a protocol, with the exception of type aliases, are requirements that must be witnessed by corresponding members in a \index{conforming type}conforming type. The protocol's properties, subscripts, and methods are called \IndexDefinition{value requirement}\emph{value requirements}. They don't have bodies, but are otherwise like member declarations of a concrete nominal type. The declared interface type of a protocol declaration is a \index{protocol type}protocol type.
Every protocol has an implicit generic parameter list with a single generic parameter named \IndexDefinition{protocol Self type@protocol \tSelf\ type}\tSelf, which abstracts over the conforming type. The declared interface type of \tSelf\ is always~\rT; protocols cannot be nested in other generic contexts (\SecRef{nested nominal types}), nor can they declare any other generic parameters.
The \texttt{associatedtype} keyword introduces an \IndexDefinition{associated type declaration}\emph{associated type declaration}, which can only appear inside of a protocol. The declared interface type is a \index{dependent member type!associated type declaration}dependent member type (\SecRef{fundamental types}). Specifically, the \index{declared interface type!associated type declaration}declared interface type of an associated type~\texttt{A} in a protocol~\texttt{P} is the \index{bound dependent member type!associated type declaration}bound dependent member type denoted \texttt{Self.[P]A}, formed from the base type of~\tSelf\ together with~\texttt{A}. A nominal type conforming to this protocol must declare a type witness for each associated type (\SecRef{type witnesses}).
Protocols can also state \IndexDefinition{associated requirement}\emph{associated requirements} on their \tSelf\ type and its dependent member types. The conforming type and its type witnesses must satisfy the protocol's associated requirements. We will review all the ways of stating associated requirements now.
\paragraph{Protocol inheritance clauses.}
A protocol can have an \index{inheritance clause!protocol declaration}inheritance clause with a list of one or more comma-separated \index{constraint type!protocol inheritance clause}constraint types. Each inheritance clause entry states an associated requirement with a subject type of \tSelf. These are additional requirements the conforming type itself must satisfy in order to conform.
An associated conformance requirement with a subject type of \tSelf\ establishes a \index{protocol inheritance|see{inherited protocol}}\IndexDefinition{inherited protocol}\emph{protocol inheritance} relationship. The protocol stating the requirement is the \emph{derived protocol}, and the protocol on the right-hand side is the \emph{base protocol}. The derived protocol is said to \emph{inherit} from (or sometimes, \emph{refine}) the base protocol. A \index{qualified lookup!protocol inheritance}qualified lookup will search through all base protocols, when the lookup begins at a derived protocol or one of its concrete conforming types.
For example, the standard library's \texttt{Collection} protocol inherits from \texttt{Sequence} by stating the associated requirement $\ConfReq{Self}{Sequence}$:
\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 in the inheritance clause:
\begin{Verbatim}
protocol BoxProtocol: AnyObject {...}
\end{Verbatim}
Protocols can also limit their conforming types to subclasses of some superclass:
\begin{Verbatim}
class Plant {}
class Animal {}
protocol Duck: Animal {}
class MockDuck: Plant, Duck {} // error: not a subclass of Animal
\end{Verbatim}
A protocol is \IndexDefinition{class-constrained protocol}\emph{class-constrained} if the $\ConfReq{Self}{AnyObject}$ \index{associated layout requirement}associated layout requirement is either explicitly stated, or a consequence of some other associated requirement. We'll say more about the semantics of protocol inheritance clauses and name lookup in \SecRef{requirement sig}, \SecRef{identtyperepr}, and \ChapRef{building generic signatures}.
\paragraph{Primary associated types.}
A protocol can declare a list of \IndexDefinition{primary associated type}\emph{primary associated types} with a syntax resembling that of a generic parameter list:
\begin{Verbatim}
protocol IteratorProtocol<Element> {
associatedtype Element
mutating func next() -> Element?
}
\end{Verbatim}
While generic parameter lists introduce new generic parameter declarations, the entries in the primary associated type list reference an \emph{existing} associated type declaration, either in the protocol itself, or some base protocol.
A \index{parameterized protocol type}\emph{parameterized protocol type} can be formed from a reference to a protocol with primary associated types, by taking a list of generic argument types, one for each primary associated type. On the right-hand side of a conformance requirement, a parameterized protocol type decomposes into a conformance requirement to the protocol, followed by a series of same-type requirements. The following are equivalent:
\begin{Verbatim}
func sumOfSquares<I>(_: I) -> Int
where I: IteratorProtocol<Int> {...}
func sumOfSquares<I>(_: I) -> Int
where I: IteratorProtocol, I.Element == Int {...}
\end{Verbatim}
More details appear in \SecRef{requirement desugaring}. Parameterized protocol types and primary associated types were added to the language in \IndexSwift{5.7}Swift~5.7~\cite{se0346}.
\paragraph{Associated requirements.}
An associated type declaration can have an \IndexDefinition{inheritance clause!associated type declaration}inheritance clause, consisting of one or more comma-separated constraint types. Each entry defines a requirement on the declared interface type of the associated type declaration, so we get $\ConfReq{Self.Data}{Codable}$ and $\ConfReq{Self.Data}{Hashable}$ below:
\begin{Verbatim}
associatedtype Data: Codable, Hashable
\end{Verbatim}
An associated type declaration can also have a trailing \Index{where clause@\texttt{where} clause!associated type declaration}\texttt{where} clause, which allows associated requirements to be stated in full generality. The standard library \texttt{Sequence} protocol showcases both primary associated types, and associated requirements:
\begin{Verbatim}
protocol Sequence<Element> {
associatedtype Iterator: IteratorProtocol
associatedtype Element where Element == Iterator.Element
func makeIterator() -> Iterator
}
\end{Verbatim}
The associated conformance requirement on \texttt{Self.Iterator} could have been stated using a \texttt{where} clause instead:
\begin{Verbatim}
associatedtype Iterator where Iterator: IteratorProtocol
\end{Verbatim}
A \Index{where clause@\texttt{where} clause!protocol declaration}\texttt{where} clause can also be attached to the protocol itself; there is no semantic difference between that and attaching it to an associated type declaration:
\begin{Verbatim}
protocol Sequence where Iterator: IteratorProtocol,
Element == Iterator.Element {...}
\end{Verbatim}
Finally, we can explicitly qualify the member types with \tSelf:
\begin{Verbatim}
protocol Sequence where Self.Iterator: IteratorProtocol,
Self.Element == Self.Iterator.Element {...}
\end{Verbatim}
In all cases, we state the same two associated requirements. Our notation is to append a subscript with the protocol name declaring the requirement:
\begin{gather*}
\ConfReq{Self.Iterator}{IteratorProtocol}_\texttt{Sequence}\\
\SameReq{Self.Element}{Self.Iterator.Element}_\texttt{Sequence}
\end{gather*}
Let's summarize all the ways of stating associated requirements in a protocol~\texttt{P}:
\begin{itemize}
\item The protocol can state an inheritance clause. Each entry defines a conformance, superclass or layout requirement with a subject type of \tSelf.
\item An associated type declaration \texttt{A} can state an inheritance clause. Each entry defines a conformance, superclass or layout requirement with a subject type of \texttt{Self.[P]A}.
\item Arbitrary associated requirements can be stated in \Index{where clause@\texttt{where} clause!protocol declaration}trailing \texttt{where} clauses, attached to the protocol or any of its associated types, in any combination.
\end{itemize}
A protocol's associated requirements are collected in its requirement signature, which we will see is dual to a generic signature in some sense (\SecRef{requirement sig}). How concrete types satisfy the requirement signature will be discussed in \ChapRef{conformances}.
\paragraph{Self requirements.}
The \Index{where clause@\texttt{where} clause!protocol declaration}\texttt{where} clause of a protocol method or subscript requirement cannot constrain \tSelf\ or its associated types. For example, the following protocol is rejected, because there would be no way to implement the \texttt{minElement()} requirement in a concrete conforming type whose \texttt{Element} type is \emph{not} \texttt{Comparable}:
\begin{Verbatim}
protocol SetProtocol {
associatedtype Element // we want `where Element: Comparable' here
func minElement() -> Element where Element: Comparable // error
}
\end{Verbatim}
\paragraph{History.}
Older releases of Swift permitted protocols and associated types to state constraint types in their inheritance clauses, but more general associated requirements did not exist. Associated requirements were introduced when the trailing \texttt{where} clause syntax was generalized to associated types and protocols in \IndexSwift{4.0}Swift~4~\cite{se0142}.
\section{Functions}\label{function decls}
A \IndexDefinition{function declaration}function declaration can appear at the top level of a source file, as a member of a nominal type or extension (which we recall is called a method declaration), or as a \IndexDefinition{local function declaration}\emph{local function} nested inside of another function. In this section, we will describe the computation of the interface type of a function declaration, and then conclude with a discussion how closure expressions and local functions capture values.
The \IndexDefinition{interface type request}\Request{interface type request} computes the interface type of a function declaration. This is a \index{function type}function type or \index{generic function type}generic function type, constructed from the interface types of the function's parameter declarations, together with its return type, and generic signature, if any. If no return type is given, it becomes the empty tuple type~\texttt{()}:
\begin{Verbatim}
func f(x: Int, y: String) -> Bool {...}
// Interface type: (Int, String) -> Bool
func g() {...}
// Interface type: () -> ()
\end{Verbatim}
\paragraph{Method declarations.}
In addition to the formal parameters declared in its parameter list, a method declaration also has an implicit \texttt{self} parameter, to receive the value on the left-hand side of the ``\texttt{.}'' in the \index{method call expression}method call expression. The interface type of a method declaration is a function type which receives the \IndexDefinition{self parameter declaration}\texttt{self} parameter, and returns another function which then takes the method's formal parameters. The ``\texttt{->}'' syntax for a function type associates to the right, so \verb|A -> B -> C| means \verb|A -> (B -> C)|:
\begin{Verbatim}
struct Universe {
func wormhole(x: Int, y: String) -> Bool {...}
// Interface type: (Universe) -> (Int, String) -> Bool
static func bigBang() {}
// Interface type: (Universe.Type) -> () -> ()
mutating func teleport() {}
// Interface type: (inout Universe) -> () -> ()
}
\end{Verbatim}
The interface type of the \texttt{self} parameter is derived as follows:
\begin{itemize}
\item We start with the \IndexDefinition{self interface type}\emph{self interface type} of the method's parent declaration context. In a struct, enum or class, this is the same as the \index{declared interface type!self interface type}declared interface type. In a protocol, this is the protocol \IndexSelf\tSelf\ type (\SecRef{protocols}). In an extension, the self interface type is that of the extended type.
\item If the method is declared inside a class, and if it returns the \Index{dynamic Self type@dynamic \tSelf\ type}dynamic \tSelf\ type, we wrap the type in the dynamic \tSelf\ type (\SecRef{misc types}).
\item If the method is \IndexDefinition{static method declaration}\texttt{static}, we wrap the type in a \index{metatype type}metatype.
\item If the method is \texttt{mutating}, we pass the \texttt{self} parameter \texttt{inout}.
\end{itemize}
\begin{figure}[b!]\captionabove{The method call \texttt{universe.wormhole(x:~1, y:~"hi")}}\label{method call expr}
\begin{center}
\begin{tikzpicture}[%
grow via three points={one child at (0.5,-0.7) and
two children at (0.5,-0.7) and (0.5,-1.4)},
edge from parent path={[->] (\tikzparentnode.south) |- (\tikzchildnode.west)}]
\node [class] {\vphantom{p}call: \texttt{universe.wormhole(x:~1, y:~"hi")}}
child { node [class] {\vphantom{p}self call: \texttt{universe.wormhole}}
child { node [class] {\vphantom{p}callee: \texttt{Universe.wormhole}}}
child { node [class] {\vphantom{p}declaration reference: \texttt{universe}}}}
child [missing] {}
child [missing] {}
child { node [class] {\vphantom{p}argument list: \texttt{(x:~1, y:~"hi")}}
child { node [class] {\vphantom{p}literal: \texttt{1}}}
child { node [class] {\vphantom{p}literal: \texttt{"hi"}}}}
child [missing] {}
child [missing] {}
child [missing] {};
\end{tikzpicture}
\end{center}
\end{figure}
Let's compare the interface type of a method declaration with the structure of a method call expression in the abstract syntax tree, shown in \FigRef{method call expr}:
\begin{itemize}
\item The outer expression's callee, \texttt{universe.wormhole}, is itself a call expression, so we must evaluate this inner call expression first.
The inner call expression applies the argument \texttt{universe} to the \texttt{self} parameter of \texttt{Universe.wormhole()}. This represents the method lookup. The return type of the inner call expression is \verb|(Int, String) -> Bool|.
\item The outer call expression applies the argument list \verb|(x: 1, y: "hi")| to the result of the inner call expression. This represents the method call itself, with a return type of \texttt{Bool}.
\end{itemize}
The extra function call disappears in \index{SILGen}SILGen, where we lower a method to a SIL function that receives all formal parameters and the \texttt{self} parameter at once.
A partially-applied method reference, such as \texttt{universe.wormhole}, can also be used as a value of type \verb|(Int, String) -> Bool|. This binds the \texttt{self} parameter but does not call the method. We handle this by wrapping the method reference in a closure that invokes the method; this closure has the same type as the method reference. In the \index{lambda calculus}lambda calculus formalism, this is what's known as \index{eta expansion}\emph{$\eta$-expansion}:
\begin{Verbatim}
{ x, y in universe.wormhole(x: x, y: y) }
\end{Verbatim}
The \index{unapplied function reference}unapplied form, \texttt{Universe.wormhole}, desugars into a closure returning a closure:
\begin{Verbatim}
{ mySelf in { x y in mySelf.wormhole(x: x, y: y) } }
\end{Verbatim}
This desugaring simplifies SILGen, because we only need to implement a lowering for fully-applied method calls that pass all formal parameters and \texttt{self} at once.
\begin{wrapfigure}[25]{l}{17.2em}
\begin{minipage}{17em}
\begin{Verbatim}
struct Example {
func instanceMethod() {}
static func staticMethod() {}
struct Lookup {
func innerMethod() {}
func test() {
instanceMethod() // bad
staticMethod() // ok
innerMethod() // ok
}
}
func anotherMethod(x: Int) {
struct Local {
func test() {
print(x) // bad
}
}
}
}
\end{Verbatim}
\end{minipage}
\end{wrapfigure}
All function declarations must be followed by a body in the source language, except for protocol requirements. A function body can contain statements, expressions, and other declarations. (Unlike types and declarations, we will not exhaustively cover all statements and expressions in this book.) The example on the left shows some call expressions.
In a method body, an unqualified reference to a member of the innermost nominal type declaration is interpreted as having an implicit ``\texttt{self.}'' qualification. Thus, instance methods can refer to other instance methods this way, and static methods can refer to other static methods.
An unqualified reference to a member of an outer nominal type can only be made if the member is static, because there is no ``outer \texttt{self} value'' to invoke the method with; a \emph{value} of the nested type does not contain a \emph{value} of its parent type.
For the same reason, methods inside \index{local type declaration}local types cannot refer to local variables declared outside of the local type. (Contrast this with \index{Java}Java inner classes for example, which can be declared as \texttt{static} or instance members of their outer class; a non-\texttt{static} inner class captures a ``\texttt{this}'' reference from the outer class. Inner classes nested in methods can also capture local variables in Java.)
\paragraph{Constructor declarations.}
\IndexDefinition{constructor declaration}Constructor declarations are introduced with the \texttt{init} keyword. The parent context of a constructor must be a nominal type or extension.
From the outside, the interface type of a constructor looks like a static method that returns a new instance of the type, but inside the constructor, \texttt{self} is the instance being initialized, so the interface type of \texttt{self} is the nominal type, and not its metatype. In a struct or enum, \texttt{self} is also \texttt{inout}. Constructors can delegate to other constructors in various ways. To model the delegation with a call expression, the \IndexDefinition{initializer interface type}\emph{initializer interface type} describes the type of an in-place initialization at a location provided by the caller:
\begin{Verbatim}
struct Universe {
init(age: Int) {...}
// Interface type: (Universe.Type) -> (Int) -> Universe
// Initializer interface type: (inout Universe) -> (Int) -> Universe
}
\end{Verbatim}
\paragraph{Destructor declarations.}
\IndexDefinition{destructor declaration}Destructor declarations are introduced with the \texttt{deinit} keyword. They can only appear inside classes. They have no formal parameters, no generic parameter list, no \texttt{where} clause, and no return type.
\paragraph{Local contexts.}
A \IndexDefinition{local context}\emph{local context} is any declaration context that is not a module, source file, type declaration or extension. Swift allows variable, function and type declarations to appear in local context. The following are local contexts:
\begin{itemize}
\item \index{top-level code declaration}Top-level code declarations.
\item Function declarations.
\item \index{closure expression}Closure expressions.
\item If a variable is not itself in local context (for example, it's a member of a nominal type declaration), then its \index{initial value expression}initial value expression defines a new local context.
\item \index{subscript declaration}Subscript and \index{enum element declaration}enum element declarations declarations are local contexts, because they can contain parameter declarations (and also a generic parameter list, in the case of a subscript).
\end{itemize}
Local functions and closures can \IndexDefinition{captured value}\emph{capture} references to other local declarations from outer scopes. We use the standard technique of \IndexDefinition{closure conversion}\emph{closure conversion} to lower functions with captured values into ones without. We can understand this process as introducing an additional parameter for each captured value, followed by a walk to replace references to captured values with references to the corresponding parameters in the function body. In Swift, this is part of \index{SILGen}SILGen's lowering process, and not a separate transformation on the abstract syntax tree.
The \IndexDefinition{capture info request}\Request{capture info request} computes the list of declarations captured by the given function and all of its nested local functions and closure expressions.
\begin{wrapfigure}[10]{l}{10.6em}
\begin{minipage}{10.5em}
\begin{Verbatim}
func f() {
let x = 0, y = 0
func g() {
var z = 0
print(x)
func h() {
print(y, z)
}
}
}
\end{Verbatim}
\end{minipage}
\end{wrapfigure}
Consider the three nested functions shown on the left. We proceed to compute their captures from the inside out.
The innermost function~\texttt{h()} captures \texttt{y}~and~\texttt{z}. The middle function~\texttt{g()} captures~\texttt{x}. It also captures~\texttt{y}, because~\texttt{h()} captures~\texttt{y}, but it does not capture~\texttt{z}, because~\texttt{z} is declared by~\texttt{g()} itself. Finally,~\texttt{f()} is declared at the top level, so it does not have any captures.
We can summarize this as follows (see \AppendixRef{math summary} for a summary of set notation):
% FIXME
\begin{quote}
\qquad\qquad
\begin{tabular}{lll}
\toprule
\textbf{Function}&\textbf{Captures}\\
\midrule
\texttt{f()}&$\varnothing$\\
\texttt{g()}&$\{\texttt{x},\,\texttt{y}\}$\\
\texttt{h()}&$\{\texttt{y},\,\texttt{z}\}$\\
\bottomrule
\end{tabular}
\end{quote}
\bigskip
\begin{algorithm}[Compute closure captures]\label{closure captures algorithm}
As input, takes the type-checked body of a \index{closure function}closure expression or \index{local function declaration}local function~$F$. Outputs the \index{set}set of captures of~$F$.
\begin{enumerate}
\item Initialize the return value with an \index{empty set}empty set, $C\leftarrow\varnothing$.
\item Recursively walk the type-checked body of $F$ and handle each element:
\item (Declaration references) If $F$ contains an expression that references some local variable or local function~$d$ by name, let $\texttt{PARENT}(d)$ denote the declaration context containing~$d$. This is either $F$ itself, or some outer local context, because we found $d$ by unqualified lookup from~$F$.
If $\texttt{PARENT}(d)\neq F$, set $C\leftarrow C\cup\{d\}$.
\item (Nested closures) If $F$ contains a nested closure expression or local function $F^\prime\!$, then any captures of $F^\prime$ not declared by~$F$ are also captures of~$F$.
Recursively compute the captures of $F^\prime\!$. For each $d$ captured by $F^\prime$ such that $\texttt{PARENT}(d)\neq F$, set $C\leftarrow C\cup\{d\}$.
\item (Local types) If $F$ contains a local type, do not walk into the children of the local type. Local types do not capture values; we enforce this below.
\item (Diagnose) After the recursive walk, consider each element $d\in C$. If the path of parent declaration contexts from $F$ to $d$ contains a nominal type declaration, we have an unsupported capture inside a local type. Diagnose an error.
\item Return $C$.
\end{enumerate}
\end{algorithm}
\begin{wrapfigure}[9]{r}{16.5em}
\begin{minipage}{16.5em}
\begin{Verbatim}
func f() {
let x = 0, y = 0, z = 0
func g() { print(x); h() }
func h() { print(y); g() }
func i() { print(z); h() }
}
\end{Verbatim}
\end{minipage}
\end{wrapfigure}
Local functions can also reference each other recursively. Consider the functions shown on the right and notice how \texttt{f()} and \texttt{g()} are mutually recursive. At runtime, we cannot represent this by forming two closure contexts where each one retains the other, because then neither context will ever be released.
We use a second algorithm to obtain the list of \IndexDefinition{lowered captures}\emph{lowered captures}, by replacing any captured local functions with their corresponding capture lists, repeating this until fixed point. The final list contains variable declarations only. With our example, the captures and lowered captures of each function are as follows:
\begin{center}
\begin{tabular}{lll}
\toprule
\textbf{Function}&\textbf{Captures}&\textbf{Lowered}\\
\midrule
\texttt{f()}&$\varnothing$&$\varnothing$\\
\texttt{g()}&$\{\texttt{x},\,\texttt{h()}\}$&$\{\texttt{x},\,\texttt{y}\}$\\
\texttt{h()}&$\{\texttt{y},\,\texttt{g()}\}$&$\{\texttt{x},\,\texttt{y}\}$\\
\texttt{i()}&$\{\texttt{z},\,\texttt{h()}\}$&$\{\texttt{x},\,\texttt{y},\,\texttt{z}\}$\\
\bottomrule
\end{tabular}
\end{center}
(As a special case, if a set of local functions reference each other but capture no other state from the outer declaration context, their lowered captures will be empty, so no runtime context allocation is necessary.)
\begin{algorithm}[Compute lowered closure captures]\label{lowered closure captures algorithm}
As input takes the type-checked body of a \index{closure function}closure expression or \index{local function declaration}local function~$F$. Outputs the \index{set}set of variable declarations transitively captured by~$F$.
\begin{enumerate}
\item Initialize the set $C\leftarrow\varnothing$; this will be the return value. Initialize an empty worklist. Initialize an empty visited set. Add $F$ to the worklist.
\item If the worklist is empty, return $C$. Otherwise, remove the next function $F$ from the worklist.
\item If $F$ is in the visited set, go back to Step~2. Otherwise, add $F$ to the visited set.
\item Compute the captures of~$F$ using \AlgRef{closure captures algorithm} and consider each capture~$d$. If~$d$ is a local variable declaration, set $C\leftarrow C\cup\{d\}$. If~$d$ is a local function declaration, add~$d$ to the worklist.
\item Go back to Step~2.
\end{enumerate}
\end{algorithm}
This completely explains captures of \texttt{let} variables, but mutable \texttt{var} variables and \texttt{inout} parameters merit further explanation.
A \index{non-escaping function type}\emph{non-escaping} closure can capture a \texttt{var} or \texttt{inout} by simply capturing the memory address of the storage location. This is safe, because a non-escaping closure cannot outlive the dynamic extent of the storage location.
An \index{escaping function type}\texttt{@escaping} closure can also capture a \texttt{var}, which requires promoting the \texttt{var} to a \index{boxing}heap-allocated box with a reference count, with all variable accesses indirecting through the box. The below example can be found in every \index{Lisp}Lisp textbook. Each invocation of \texttt{counter()} allocates a new counter value on the heap, and returns three closures that reference the box; the box itself is completely hidden by the abstraction:
\begin{Verbatim}
func counter() -> (read: () -> Int, inc: () -> (), dec: () -> ()) {
var count = 0 // promoted to a box
return ({ count }, { count += 1 }, { count -= 1 })
}
\end{Verbatim}
Before \IndexSwift{3.0}Swift~3.0, \texttt{@escaping} closures were permitted to capture \texttt{inout} parameters as well. To make this safe, the contents of the \texttt{inout} parameter were first copied into a heap-allocated box, which was captured by the closure. The contents of this box were then copied back before the function returned to its caller. This was essentially equivalent to doing the following transform, where we introduced \verb|_n| by hand:
\begin{Verbatim}
func changeValue(_ n: inout Int) {
var _n = n // copy the value
let escapingFn = {
_n += 1 // capture the box
}
n = _n // write it back
}
\end{Verbatim}
In this scheme, if the closure outlives the dynamic extent of the \texttt{inout} parameter, any subsequent writes from within the closure are silently dropped. This was a source of user confusion, so Swift~3.0 banned \texttt{inout} captures from escaping closures instead~\cite{se0035}.
In SIL, a closure is represented abstractly, as the result of this partial application operation. The mechanics of how the partially-applied function value actually stores its captures---the partially-applied arguments---are left up to IRGen. In IRGen, we allocate space for storing the captures (either on the stack for a \index{non-escaping function type}non-escaping function type, otherwise it's on the heap for \texttt{@escaping}), and then we emit a thunk, which takes a pointer to the context as an argument, unpacks the captured values from the context, and passes them as individual arguments to the original function. This thunk together with the context forms a \IndexDefinition{thick function}\emph{thick function} value which can then be passed around.
If nothing is captured (or if all captured values are zero bytes in size), we can pass a null pointer as the context, without performing a heap allocation. If there is exactly one captured value and this value can be represented as a reference-counted pointer, we can also elide the allocation by passing the captured value as the context pointer instead. For example, if a closure's single capture is an instance of a \index{class type}class type, nothing is allocated. If the single capture is the heap-allocated box that wraps a \texttt{var}, we must still allocate the box for the \texttt{var}, but we avoid a second context allocation.
\section{Storage}\label{other decls}
\IndexDefinition{storage declaration}
\index{l-value type}
Storage declarations represent locations that can be read and written.
\paragraph{Parameter declarations.} Functions, enum elements and subscripts can have parameter lists; each parameter is represented by a \IndexDefinition{parameter declaration}parameter declaration. Parameter declarations are a kind of variable declaration.
\paragraph{Variable declarations.} \IndexDefinition{variable declaration}Variables that are not parameters are introduced with \texttt{var} and \texttt{let}. A variable might either be \emph{stored} or \emph{computed}; the behavior of a computed variable is given by its accessor implementations. The interface type of a variable is the stored value type, possibly wrapped in a reference storage type if the variable is declared as \texttt{weak} or \texttt{unowned}. The \IndexDefinition{value interface type}\emph{value interface type} of a variable is the storage type without any wrapping.
\IndexDefinition{pattern binding declaration}
\IndexDefinition{pattern binding entry}
\IndexDefinition{pattern}
\IndexDefinition{initial value expression}
Variable declarations are always created alongside a \emph{pattern binding declaration} which represents the various ways in which variables can be bound to values in Swift. A pattern binding declaration consists of one or more \emph{pattern binding entries}. Each pattern binding entry has a \emph{pattern} and an optional \emph{initial value expression}. A pattern declares zero or more variables.
Here is a pattern binding declaration with a single entry that does not declare any variables:
\begin{Verbatim}
let _ = ignored()
\end{Verbatim}
Here is a pattern binding declaration with a single entry, where the pattern declares a single variable:
\begin{Verbatim}
let x = 123
\end{Verbatim}
We can write a more complex pattern, for example storing the first element of a tuple while discarding the second element:
\begin{Verbatim}
let (x, _) = (123, "hello")
\end{Verbatim}
Here is a pattern binding declaration with a single entry, whose pattern delares two variables \texttt{x} and \texttt{y}:
\begin{Verbatim}
let (x, y) = (123, "hello")
\end{Verbatim}
Here is a pattern binding declaration with two entries, declaring \texttt{x} and \texttt{y} respectively:
\begin{Verbatim}
let x = 123, y = "hello"
\end{Verbatim}
And finally, here we have two pattern binding declarations, where each pattern binding declaration has a single entry declaring a single variable:
\begin{Verbatim}
let x = 123
let y = "hello"
\end{Verbatim}
When a pattern binding declaration appears outside of a local context, each entry must declare at least one variable, so we reject both of the following:
\begin{Verbatim}
let _ = 123
struct S {
let _ = "hello"
}
\end{Verbatim}
\index{typed pattern}
\index{tuple pattern}
A funny quirk of the pattern grammar is that typed patterns and tuple patterns do not compose in the way one might think. If ``\texttt{let x:~Int}'' is a typed pattern declaring a variable \texttt{x} type with annotation \texttt{Int}, and ``\texttt{let (x, y)}'' is a tuple pattern declaring two variables \texttt{x} and \texttt{y}, we might expect ``\texttt{let~(x:~Int,~y:~String)}'' to declare two variables \texttt{x} and \texttt{y} with type annotations \texttt{Int} and \texttt{String} respectively; what actually happens is we get a tuple pattern declaring two variables named \texttt{Int} and \texttt{String} that binds a two-element tuple with \emph{labels} \texttt{x} and \texttt{y}:
\begin{Verbatim}
let (x: Int, y: String) = (x: 123, y: "hello")
print(Int) // huh? prints 123
print(String) // weird! prints "hello"
\end{Verbatim}
\paragraph{Subscript declarations.} \IndexDefinition{subscript declaration}Subscripts are introduced with the \texttt{subscript} keyword. They can only appear as members of nominal types and extensions. The interface type of a subscript is a function type taking the index parameters and returning the storage type. The value interface type of a subscript is just the storage type. For historical reasons, the interface type of a subscript does not include the \tSelf\ clause, the way that method declarations do. Subscripts can either be instance or static members; static subscripts were introduced in \IndexSwift{5.1}Swift~5.1 \cite{se0254}.
\paragraph{Accessor declarations.}
Each storage declaration has a \IndexDefinition{accessor declaration}set of accessor declarations, which are a special kind of function declaration. The accessor declarations are siblings of the storage declaration in the declaration context hierarchy. The interface type of an accessor depends the accessor kind. For example, getters return the value, and setters take the new value as a parameter. Property accessors do not take any other parameters; subscript accessors also take the subscript's index parameters. We will not need any more details about accessor and storage declarations in this book.
\section{Source Code Reference}\label{declarationssourceref}
Key source files:
\begin{itemize}
\item \SourceFile{include/swift/AST/Decl.h}
\item \SourceFile{include/swift/AST/DeclContext.h}
\item \SourceFile{lib/AST/Decl.cpp}
\item \SourceFile{lib/AST/DeclContext.cpp}
\end{itemize}
Other source files:
\begin{itemize}
\item \SourceFile{include/swift/AST/DeclNodes.def}
\item \SourceFile{include/swift/AST/ASTVisitor.h}
\item \SourceFile{include/swift/AST/ASTWalker.h}
\end{itemize}
\IndexSource{declaration}
\apiref{Decl}{class}
Base class of declarations. \FigRef{declhierarchy} shows various subclasses, which correspond to the different kinds of declarations defined previously in this chapter.
\begin{figure}\captionabove{The \texttt{Decl} class hierarchy}\label{declhierarchy}
\begin{center}
\begin{tikzpicture}[%
grow via three points={one child at (0.5,-0.7) and
two children at (0.5,-0.7) and (0.5,-1.4)},
edge from parent path={[->] (\tikzparentnode.south) |- (\tikzchildnode.west)}]
\node [class] {\texttt{\vphantom{p}Decl}}
child { node [class] {\texttt{\vphantom{p}ValueDecl}}
child { node [class] {\texttt{\vphantom{p}TypeDecl}}
child { node [class] {\texttt{\vphantom{p}NominalTypeDecl}}
child { node [class] {\texttt{\vphantom{p}StructDecl}}}
child { node [class] {\texttt{\vphantom{p}EnumDecl}}}
child { node [class] {\texttt{\vphantom{p}ClassDecl}}}
child { node [class] {\texttt{\vphantom{p}ProtocolDecl}}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child { node [class] {\texttt{\vphantom{p}TypeAliasDecl}}}
child { node [class] {\texttt{\vphantom{p}AbstractTypeParamDecl}}
child { node [class] {\texttt{\vphantom{p}GenericTypeParamDecl}}}
child { node [class] {\texttt{\vphantom{p}AssociatedTypeDecl}}}
}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child { node [class] {\texttt{\vphantom{p}AbstractFunctionDecl}}
child { node [class] {\texttt{\vphantom{p}FuncDecl}}
child { node [class] {\texttt{\vphantom{p}AccessorDecl}}}
}
child [missing] {}
child { node [class] {\texttt{\vphantom{p}ConstructorDecl}}}
child { node [class] {\texttt{\vphantom{p}DestructorDecl}}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child { node [class] {\texttt{\vphantom{p}AbstractStorageDecl}}
child { node [class] {\texttt{\vphantom{p}VarDecl}}
child { node [class] {\texttt{\vphantom{p}ParamDecl}}}
}
child [missing] {}
child { node [class] {\texttt{\vphantom{p}SubscriptDecl}}}
}
child [missing] {}
child [missing] {}
child [missing] {}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child { node [class] {\texttt{\vphantom{p}ExtensionDecl}}};
\end{tikzpicture}
\end{center}
\end{figure}
\IndexSource{synthesized declaration}
Instances are always allocated in the permanent arena of the \texttt{ASTContext}, either when the declaration is parsed or synthesized. The top-level \verb|isa<>|, \verb|cast<>| and \verb|dyn_cast<>| template functions support dynamic casting from \texttt{Decl *} to any of its subclasses.
\begin{itemize}
\item \texttt{getDeclContext()} returns the parent \texttt{DeclContext} of this declaration.
\item \texttt{getInnermostDeclContext()} if this declaration is also a declaration context, returns the declaration as a \texttt{DeclContext}, otherwise returns the parent \texttt{DeclContext}.
\item \texttt{getASTContext()} returns the singleton AST context from a declaration.
\end{itemize}
\index{visitor pattern}
\IndexSource{declaration kind}
\index{exhaustive switch}
\index{statement}
\index{expression}
\index{type representation}
\paragraph{Visitors.}
To exhaustively handle each kind of declaration, the simplest way is to switch over the kind, which is an instance of the \texttt{DeclKind} enum, like this:
\begin{Verbatim}
Decl *decl = ...;
switch (decl->getKind()) {
case DeclKind::Struct: {
auto *structDecl = decl->castTo<StructDecl>();
...
}
case DeclKind::Enum:
...
case DeclKind::Class:
...
}
\end{Verbatim}
However, just as with types, is can be more convenient to use the visitor pattern, by subclassing \texttt{ASTVisitor} and overriding various \texttt{visit\emph{Kind}Decl()} methods. The visitor's \texttt{visit()} method performs the switch and dynamic cast dance above, and calls each method:
\begin{Verbatim}
class MyVisitor: public ASTVisitor<MyVisitor> {
public:
void visitStructDecl(StructType *decl) {
...
}
};
MyVisitor visitor;
Decl *decl = ...;
visitor.visit(decl);
\end{Verbatim}
The \texttt{ASTVisitor} also defines various methods corresponding to abstract base classes in the \texttt{Decl} hierarchy, so for example an override of \texttt{visitNominalTypeDecl()} will handle all nominal type declarations at once. The \texttt{ASTVisitor} is more general than just visiting declarations; it also supports visiting statements, expressions, and type representations.
A more elaborate form is implemented by the \texttt{ASTWalker}. While the visitor visits a single declaration, the walker traverses nested declarations, statements and expressions in a pre-order walk.
\IndexSource{value declaration}
\apiref{ValueDecl}{class}
Base class of named declarations.
\IndexSource{interface type}
\begin{itemize}
\item \texttt{getDeclName()} returns the declaration's name.
\item \texttt{getInterfaceType()} returns the declaration's interface type.
\end{itemize}
\subsection*{Type Declarations}
\IndexSource{type declaration}
\IndexSource{declared interface type}
\apiref{TypeDecl}{class}
Base class of type declarations.
\begin{itemize}
\item \texttt{getDeclaredInterfaceType()} returns the type of an instance of this declaration.
\end{itemize}
\IndexSource{nominal type declaration}
\IndexSource{struct declaration}
\IndexSource{enum declaration}
\IndexSource{class declaration}
\IndexSource{nominal type declaration}
\IndexSource{self interface type}
\apiref{NominalTypeDecl}{class}
Base class of nominal type declarations. Also a \texttt{DeclContext}.
\begin{itemize}
\item \texttt{getSelfInterfaceType()} returns the self interface type of the declaration context (\SecRef{function decls}). Different from the declared interface type for protocols, where the declared interface type is a nominal but the declared self type is the generic parameter \tSelf.
\item \texttt{getDeclaredType()} returns the type of an instance of this declaration, without generic arguments. If the declaration is generic, this is an \IndexSource{unbound generic type}unbound generic type. If this declaration is not generic, this is a nominal type. This is occasionally used in diagnostics instead of the declared interface type, when the generic parameter types are irrelevant.
\end{itemize}
\IndexSource{type alias declaration}
\IndexSource{underlying type}
\apiref{TypeAliasDecl}{class}
A type alias declaration. Also a \texttt{DeclContext}.
\begin{itemize}
\item \texttt{getDeclaredInterfaceType()} returns the underlying type of the type alias declaration, wrapped in type alias type sugar.
\item \texttt{getUnderlyingType()} returns the underlying type of the type alias declaration, without wrapping it in type alias type sugar.
\end{itemize}
\subsection*{Declaration Contexts}
\IndexSource{declaration context}
\apiref{DeclContext}{class}
Base class for declaration contexts. The top-level \verb|isa<>|, \verb|cast<>| and \verb|dyn_cast<>| template functions also support dynamic casting from a \texttt{DeclContext *} to any of its subclasses. See also \SecRef{genericsigsourceref}.
\IndexSource{closure expression}
\IndexSource{source file}
\IndexSource{file unit}
There are a handful of subclasses which are not also subclasses of \texttt{Decl *}:
\begin{itemize}
\item \texttt{ClosureExpr}.
\item \texttt{FileUnit} and its various subclasses, such as \texttt{SourceFile}.
\item A few other less interesting ones found in the source.
\end{itemize}
Utilities for understanding the nesting of declaration contexts:
\begin{itemize}
\item \texttt{getAsDecl()} if declaration context is also a declaration, returns the declaration, otherwise returns \texttt{nullptr}.
\item \texttt{getParent()} returns the parent declaration context.
\item \texttt{isModuleScopeContext()} returns true if this is a \texttt{ModuleDecl} or \texttt{FileUnit}.
\item \texttt{isTypeContext()} returns true if this is a nominal type declaration or an extension.
\item \texttt{isLocalContext()} returns true if this is not a module scope context or type context.
\item \texttt{getParentModule()} returns the module declaration at the root of the hierarchy.
\item \texttt{getModuleScopeContext()} returns the innermost parent which is a \texttt{ModuleDecl} or \texttt{FileUnit}.
\item \texttt{getParentSourceFile()} returns the innermost parent which is a source file, or \texttt{nullptr} if this declaration context was not parsed from source.
\item \texttt{getInnermostDeclarationDeclContext()} returns the innermost parent which is also a declaration, or \texttt{nullptr}.
\item \texttt{getInnermostDeclarationTypeContext()} returns the innermost parent which is also a nominal type or extension, or \texttt{nullptr}.
\end{itemize}
Operations on type contexts:
\begin{itemize}
\item \texttt{getSelfNominalDecl()} returns the nominal type declaration if this is a type context, or \texttt{nullptr}.
\item \texttt{getSelfStructDecl()} as above but result is a \texttt{StructDecl *} or \texttt{nullptr}.
\item \texttt{getSelfEnumDecl()} as above but result is a \texttt{EnumDecl *} or \texttt{nullptr}.
\item \texttt{getSelfClassDecl()} as above but result is a \texttt{ClassDecl *} or \texttt{nullptr}.
\item \texttt{getSelfProtocolDecl()} as above but result is a \texttt{ProtocolDecl *} or \texttt{nullptr}.
\item \texttt{getDeclaredInterfaceType()} delegates to the method on \texttt{NominalTypeDecl} or \texttt{ExtensionDecl} as appropriate.
\item \texttt{getSelfInterfaceType()} is similar.
\end{itemize}
Generic parameters and requirements:
\begin{itemize}
\item \texttt{isGenericContext()} answers true if either this generic context or one of its parents has a generic parameter list.
\item \texttt{isInnermostContextGeneric()} answers if this declaration context itself has a generic parameter list. Compare with \texttt{isGenericContext()}.
\end{itemize}
\subsection*{Generic Contexts}
Key source files:
\begin{itemize}
\item \SourceFile{include/swift/AST/GenericParamList.h}
\item \SourceFile{include/swift/AST/Requirement.h}
\item \SourceFile{lib/AST/GenericParamList.cpp}
\item \SourceFile{lib/AST/NameLookup.cpp}
\item \SourceFile{lib/AST/Requirement.cpp}
\end{itemize}
\IndexSource{generic context}
\IndexSource{generic declaration}
\IndexSource{parsed generic parameter list}
\apiref{GenericContext}{class}
Subclass of \texttt{DeclContext}. Base class for declaration kinds which can have a generic parameter list. See also \SecRef{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. This is equivalent to calling \texttt{DeclContext::isInnermostContextGeneric()}. Compare with \texttt{DeclContext::isGenericContext()}.
\item \texttt{getGenericContextDepth()} returns the \IndexSource{depth}depth of the declaration's generic parameter list, or \texttt{(unsigned)-1} if neither this declaration nor any outer declaration is generic.
\item \texttt{getTrailingWhereClause()} returns the declaration's trailing \texttt{where} clause, or \texttt{nullptr}.
\end{itemize}
Trailing \texttt{where} clauses are not preserved in serialized generic contexts. Most code should look at \texttt{GenericContext::getGenericSignature()} instead (\SecRef{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 \tSelf\ type}
\apiref{GenericParamListRequest}{class}
This \IndexSource{generic parameter list request}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 \tSelf\ 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 \IndexSource{depth}\texttt{getDepth()} returns the depth of the generic parameter declaration.
\item \IndexSource{index}\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 \IndexSource{sugared type}sugared generic parameter type for this declaration, which prints as the generic parameter's name.
\item \texttt{isOpaque()} answers if this generic parameter is associated with an \IndexSource{opaque parameter}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 \IndexSource{inheritance clause!generic parameter declaration}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 (\SecRef{genericsigsourceref}).
\apiref{GenericTypeParamType}{class}
A \IndexSource{generic parameter type}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 if this is the sugared form, otherwise returns a string of the form ``\ttgp{d}{i}''.
\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 \SecRef{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 this protocol \IndexSource{where clause@\texttt{where} clause!protocol declaration}\texttt{where} clause, or \texttt{nullptr}.
\item \texttt{getAssociatedTypes()} returns an array of all associated type declarations in this protocol.
\item \texttt{getPrimaryAssociatedTypes()} returns an array of all primary associated type declarations in this protocol.
\item \texttt{getInherited()} returns this protocol's \IndexSource{inheritance clause!protocol declaration}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 (\SecRef{genericsigsourceref}).
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 \IndexSource{inherited protocol}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{getSuperclassDecl()} returns the protocol's superclass declaration.
\end{itemize}
\apiref{AssociatedTypeDecl}{class}
An \IndexSource{associated type declaration}associated type declaration.
\begin{itemize}
\item \texttt{getTrailingWhereClause()} returns this associated type's trailing \IndexSource{where clause@\texttt{where} clause!associated type declaration}\texttt{where} clause, or \texttt{nullptr}.
\item \texttt{getInherited()} returns this associated type's \IndexSource{inheritance clause!associated type declaration}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 (\SecRef{genericsigsourceref}).
\subsection*{Function Declarations}
\IndexSource{function declaration}
\IndexSource{method self parameter}
\apiref{AbstractFunctionDecl}{class}
Base class of function-like declarations. Also a \texttt{DeclContext}.
\begin{itemize}
\item \texttt{getImplicitSelfDecl()} returns the implicit \texttt{self} parameter, if there is one.
\item \texttt{getParameters()} returns the function's parameter list.
\item \texttt{getMethodInterfaceType()} returns the type of a method without the \tSelf\ clause.
\item \texttt{getResultInterfaceType()} returns the return type of this function or method.
\end{itemize}
\apiref{ParameterList}{class}
The parameter list of \texttt{AbstractFunctionDecl}, \texttt{EnumElementDecl} or \texttt{SubscriptDecl}.
\begin{itemize}
\item \texttt{size()} returns the number of parameters.
\item \texttt{get()} returns the \texttt{ParamDecl} at the given index.
\end{itemize}
\IndexSource{constructor declaration}
\apiref{ConstructorDecl}{class}
Constructor declarations.
\begin{itemize}
\item \texttt{getInitializerInterfaceType()} returns the initializer interface type, used when type checking \texttt{super.init()} delegation.
\end{itemize}
\subsection*{Closure Conversion}
Key source files:
\begin{itemize}
\item \SourceFile{include/swift/AST/CaptureInfo.h}
\item \SourceFile{include/swift/SIL/TypeLowering.h}
\item \SourceFile{lib/AST/CaptureInfo.cpp}
\item \SourceFile{lib/Sema/TypeCheckCaptures.cpp}
\item \SourceFile{lib/SIL/IR/TypeLowering.cpp}
\end{itemize}
\IndexSource{captured value}
\IndexSource{closure conversion}
\apiref{CaptureInfo}{class}
An immutable list of captured values.
\apiref{CaptureInfoRequest::evaluate}{method}
Computes the \texttt{CaptureInfo}. This is \AlgRef{closure captures algorithm}.
\apiref{TypeLowering::getLoweredLocalCaptures()}{method}
Computes the lowered \texttt{CaptureInfo}. This is \AlgRef{lowered closure captures algorithm}.
\subsection*{Storage Declarations}
\IndexSource{storage declaration}
\apiref{AbstractStorageDecl}{class}
Base class for storage declarations.
\begin{itemize}
\item \texttt{getValueInterfaceType()} returns the type of the stored value, without \texttt{weak} or \texttt{unowned} storage qualifiers.
\end{itemize}
\IndexSource{variable declaration}
\IndexSource{property declaration}
\IndexSource{local variable declaration}
\apiref{VarDecl}{class}
Subclass of \texttt{AbstractStorageDecl}.
\IndexSource{subscript declaration}
\apiref{SubscriptDecl}{class}
Subclass of \texttt{AbstractStorageDecl} and \texttt{DeclContext}.
\end{document}
|