-
Notifications
You must be signed in to change notification settings - Fork 169
/
Copy pathDeclarations.md
3993 lines (3317 loc) · 142 KB
/
Declarations.md
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
# Declarations
Introduce types, operators, variables, and other names and constructs.
A *declaration* introduces a new name or construct into your program.
For example, you use declarations to introduce functions and methods,
to introduce variables and constants,
and to define enumeration, structure, class, and protocol types.
You can also use a declaration to extend the behavior
of an existing named type and to import symbols into your program that are declared elsewhere.
In Swift, most declarations are also definitions in the sense that they're implemented
or initialized at the same time they're declared. That said, because protocols don't
implement their members, most protocol members are declarations only. For convenience
and because the distinction isn't that important in Swift,
the term *declaration* covers both declarations and definitions.
> Grammar of a declaration:
>
> *declaration* → *import-declaration* \
> *declaration* → *constant-declaration* \
> *declaration* → *variable-declaration* \
> *declaration* → *typealias-declaration* \
> *declaration* → *function-declaration* \
> *declaration* → *enum-declaration* \
> *declaration* → *struct-declaration* \
> *declaration* → *class-declaration* \
> *declaration* → *actor-declaration* \
> *declaration* → *protocol-declaration* \
> *declaration* → *initializer-declaration* \
> *declaration* → *deinitializer-declaration* \
> *declaration* → *extension-declaration* \
> *declaration* → *subscript-declaration* \
> *declaration* → *macro-declaration* \
> *declaration* → *operator-declaration* \
> *declaration* → *precedence-group-declaration*
## Top-Level Code
The top-level code in a Swift source file consists of zero or more statements,
declarations, and expressions.
By default, variables, constants, and other named declarations that are declared
at the top-level of a source file are accessible to code
in every source file that's part of the same module.
You can override this default behavior
by marking the declaration with an access-level modifier,
as described in <doc:Declarations#Access-Control-Levels>.
There are two kinds of top-level code:
top-level declarations and executable top-level code.
Top-level declarations consist of only declarations,
and are allowed in all Swift source files.
Executable top-level code contains statements and expressions,
not just declarations,
and is allowed only as the top-level entry point for the program.
The Swift code you compile to make an executable
can contain at most one of the following approaches
to mark the top-level entry point,
regardless of how the code is organized into files and modules:
the `main` attribute,
the `NSApplicationMain` attribute,
the `UIApplicationMain` attribute,
a `main.swift` file,
or a file that contains top-level executable code.
> Grammar of a top-level declaration:
>
> *top-level-declaration* → *statements*_?_
## Code Blocks
A *code block* is used by a variety of declarations and control structures
to group statements together.
It has the following form:
```swift
{
<#statements#>
}
```
The *statements* inside a code block include declarations,
expressions, and other kinds of statements and are executed in order
of their appearance in source code.
<!--
TR: What exactly are the scope rules for Swift?
-->
<!--
TODO: Discuss scope. I assume a code block creates a new scope?
-->
> Grammar of a code block:
>
> *code-block* → **`{`** *statements*_?_ **`}`**
## Import Declaration
An *import declaration* lets you access symbols
that are declared outside the current file.
The basic form imports the entire module;
it consists of the `import` keyword followed by a module name:
```swift
import <#module#>
```
Providing more detail limits which symbols are imported ---
you can specify a specific submodule
or a specific declaration within a module or submodule.
When this detailed form is used,
only the imported symbol
(and not the module that declares it)
is made available in the current scope.
```swift
import <#import kind#> <#module#>.<#symbol name#>
import <#module#>.<#submodule#>
```
<!--
TODO: Need to add more to this section.
-->
> Grammar of an import declaration:
>
> *import-declaration* → *attributes*_?_ **`import`** *import-kind*_?_ *import-path*
>
> *import-kind* → **`typealias`** | **`struct`** | **`class`** | **`enum`** | **`protocol`** | **`let`** | **`var`** | **`func`** \
> *import-path* → *identifier* | *identifier* **`.`** *import-path*
## Constant Declaration
A *constant declaration* introduces a constant named value into your program.
Constant declarations are declared using the `let` keyword and have the following form:
```swift
let <#constant name#>: <#type#> = <#expression#>
```
A constant declaration defines an immutable binding between the *constant name*
and the value of the initializer *expression*;
after the value of a constant is set, it can't be changed.
That said, if a constant is initialized with a class object,
the object itself can change,
but the binding between the constant name and the object it refers to can't.
When a constant is declared at global scope,
it must be initialized with a value.
When a constant declaration occurs in the context of a function or method,
it can be initialized later,
as long as it's guaranteed to have a value set
before the first time its value is read.
If the compiler can prove that the constant's value is never read,
the constant isn't required to have a value set at all.
This analysis is called *definite initialization* ---
the compiler proves that a value is definitely set before being read.
> Note:
> Definite initialization
> can't construct proofs that require domain knowledge,
> and its ability to track state across conditionals has a limit.
> If you can determine that constant always has a value set,
> but the compiler can't prove this is the case,
> try simplifying the code paths that set the value,
> or use a variable declaration instead.
<!--
In the most general case,
DI reduces to the halting problem,
as shown by Rice's theorem.
-->
When a constant declaration occurs in the context of a class or structure
declaration, it's considered a *constant property*.
Constant declarations aren't computed properties and therefore don't have getters
or setters.
If the *constant name* of a constant declaration is a tuple pattern,
the name of each item in the tuple is bound to the corresponding value
in the initializer *expression*.
```swift
let (firstNumber, secondNumber) = (10, 42)
```
<!--
- test: `constant-decl`
```swifttest
-> let (firstNumber, secondNumber) = (10, 42)
```
-->
In this example,
`firstNumber` is a named constant for the value `10`,
and `secondNumber` is a named constant for the value `42`.
Both constants can now be used independently:
```swift
print("The first number is \(firstNumber).")
// Prints "The first number is 10."
print("The second number is \(secondNumber).")
// Prints "The second number is 42."
```
<!--
- test: `constant-decl`
```swifttest
-> print("The first number is \(firstNumber).")
<- The first number is 10.
-> print("The second number is \(secondNumber).")
<- The second number is 42.
```
-->
The type annotation (`:` *type*) is optional in a constant declaration
when the type of the *constant name* can be inferred,
as described in <doc:Types#Type-Inference>.
To declare a constant type property,
mark the declaration with the `static` declaration modifier.
A constant type property of a class is always implicitly final;
you can't mark it with the `class` or `final` declaration modifier
to allow or disallow overriding by subclasses.
Type properties are discussed in <doc:Properties#Type-Properties>.
<!--
- test: `class-constants-cant-have-class-or-final`
```swifttest
-> class Super { class let x = 10 }
!$ error: class stored properties not supported in classes; did you mean 'static'?
!! class Super { class let x = 10 }
!! ~~~~~ ^
-> class S { static final let x = 10 }
!$ error: static declarations are already final
!! class S { static final let x = 10 }
!! ^~~~~~
!!-
```
-->
For more information about constants and for guidance about when to use them,
see <doc:TheBasics#Constants-and-Variables> and <doc:Properties#Stored-Properties>.
> Grammar of a constant declaration:
>
> *constant-declaration* → *attributes*_?_ *declaration-modifiers*_?_ **`let`** *pattern-initializer-list*
>
> *pattern-initializer-list* → *pattern-initializer* | *pattern-initializer* **`,`** *pattern-initializer-list* \
> *pattern-initializer* → *pattern* *initializer*_?_ \
> *initializer* → **`=`** *expression*
## Variable Declaration
A *variable declaration* introduces a variable named value into your program
and is declared using the `var` keyword.
Variable declarations have several forms that declare different kinds
of named, mutable values,
including stored and computed variables and properties,
stored variable and property observers, and static variable properties.
The appropriate form to use depends on
the scope at which the variable is declared and the kind of variable you intend to declare.
> Note: You can also declare properties in the context of a protocol declaration,
> as described in <doc:Declarations#Protocol-Property-Declaration>.
You can override a property in a subclass by marking the subclass's property declaration
with the `override` declaration modifier, as described in <doc:Inheritance#Overriding>.
### Stored Variables and Stored Variable Properties
The following form declares a stored variable or stored variable property:
```swift
var <#variable name#>: <#type#> = <#expression#>
```
You define this form of a variable declaration at global scope, the local scope
of a function, or in the context of a class or structure declaration.
When a variable declaration of this form is declared at global scope or the local
scope of a function, it's referred to as a *stored variable*.
When it's declared in the context of a class or structure declaration,
it's referred to as a *stored variable property*.
The initializer *expression* can't be present in a protocol declaration,
but in all other contexts, the initializer *expression* is optional.
That said, if no initializer *expression* is present,
the variable declaration must include an explicit type annotation (`:` *type*).
As with constant declarations,
if a variable declaration omits the initializer *expression*,
the variable must have a value set before the first time it is read.
Also like constant declarations,
if the *variable name* is a tuple pattern,
the name of each item in the tuple is bound to the corresponding value
in the initializer *expression*.
As their names suggest, the value of a stored variable or a stored variable property
is stored in memory.
### Computed Variables and Computed Properties
The following form declares a computed variable or computed property:
```swift
var <#variable name#>: <#type#> {
get {
<#statements#>
}
set(<#setter name#>) {
<#statements#>
}
}
```
You define this form of a variable declaration at global scope, the local scope
of a function, or in the context of a class, structure, enumeration, or extension declaration.
When a variable declaration of this form is declared at global scope or the local
scope of a function, it's referred to as a *computed variable*.
When it's declared in the context of a class,
structure, or extension declaration,
it's referred to as a *computed property*.
The getter is used to read the value,
and the setter is used to write the value.
The setter clause is optional,
and when only a getter is needed, you can omit both clauses and simply
return the requested value directly,
as described in <doc:Properties#Read-Only-Computed-Properties>.
But if you provide a setter clause, you must also provide a getter clause.
The *setter name* and enclosing parentheses is optional.
If you provide a setter name, it's used as the name of the parameter to the setter.
If you don't provide a setter name, the default parameter name to the setter is `newValue`,
as described in <doc:Properties#Shorthand-Setter-Declaration>.
Unlike stored named values and stored variable properties,
the value of a computed named value or a computed property isn't stored in memory.
For more information and to see examples of computed properties,
see <doc:Properties#Computed-Properties>.
### Stored Variable Observers and Property Observers
You can also declare a stored variable or property with `willSet` and `didSet` observers.
A stored variable or property declared with observers has the following form:
```swift
var <#variable name#>: <#type#> = <#expression#> {
willSet(<#setter name#>) {
<#statements#>
}
didSet(<#setter name#>) {
<#statements#>
}
}
```
You define this form of a variable declaration at global scope, the local scope
of a function, or in the context of a class or structure declaration.
When a variable declaration of this form is declared at global scope or the local
scope of a function, the observers are referred to as *stored variable observers*.
When it's declared in the context of a class or structure declaration,
the observers are referred to as *property observers*.
You can add property observers to any stored property. You can also add property
observers to any inherited property (whether stored or computed) by overriding
the property within a subclass, as described in <doc:Inheritance#Overriding-Property-Observers>.
The initializer *expression* is optional in the context of a class or structure declaration,
but required elsewhere. The *type* annotation is optional
when the type can be inferred from the initializer *expression*.
This expression is evaluated the first time you read the property's value.
If you overwrite the property's initial value without reading it,
this expression is evaluated before the first time you write to the property.
<!--
- test: `overwriting-property-without-writing`
```swifttest
>> func loudConst(_ x: Int) -> Int {
>> print("initial value:", x)
>> return x
>> }
>> var x = loudConst(10)
>> x = 20
>> print("x:", x)
<< initial value: 10
<< x: 20
>> var y = loudConst(100)
>> print("y:", y)
<< initial value: 100
<< y: 100
```
-->
The `willSet` and `didSet` observers provide a way to observe (and to respond appropriately)
when the value of a variable or property is being set.
The observers aren't called when the variable or property
is first initialized.
Instead, they're called only when the value is set outside of an initialization context.
A `willSet` observer is called just before the value of the variable or property
is set. The new value is passed to the `willSet` observer as a constant,
and therefore it can't be changed in the implementation of the `willSet` clause.
The `didSet` observer is called immediately after the new value is set. In contrast
to the `willSet` observer, the old value of the variable or property
is passed to the `didSet` observer in case you still need access to it. That said,
if you assign a value to a variable or property within its own `didSet` observer clause,
that new value that you assign will replace the one that was just set and passed to
the `willSet` observer.
The *setter name* and enclosing parentheses in the `willSet` and `didSet` clauses are optional.
If you provide setter names,
they're used as the parameter names to the `willSet` and `didSet` observers.
If you don't provide setter names,
the default parameter name to the `willSet` observer is `newValue`
and the default parameter name to the `didSet` observer is `oldValue`.
The `didSet` clause is optional when you provide a `willSet` clause.
Likewise, the `willSet` clause is optional when you provide a `didSet` clause.
If the body of the `didSet` observer refers to the old value,
the getter is called before the observer,
to make the old value available.
Otherwise, the new value is stored without calling the superclass's getter.
The example below shows a computed property that's defined by the superclass
and overridden by its subclasses to add an observer.
```swift
class Superclass {
private var xValue = 12
var x: Int {
get { print("Getter was called"); return xValue }
set { print("Setter was called"); xValue = newValue }
}
}
// This subclass doesn't refer to oldValue in its observer, so the
// superclass's getter is called only once to print the value.
class New: Superclass {
override var x: Int {
didSet { print("New value \(x)") }
}
}
let new = New()
new.x = 100
// Prints "Setter was called"
// Prints "Getter was called"
// Prints "New value 100"
// This subclass refers to oldValue in its observer, so the superclass's
// getter is called once before the setter, and again to print the value.
class NewAndOld: Superclass {
override var x: Int {
didSet { print("Old value \(oldValue) - new value \(x)") }
}
}
let newAndOld = NewAndOld()
newAndOld.x = 200
// Prints "Getter was called"
// Prints "Setter was called"
// Prints "Getter was called"
// Prints "Old value 12 - new value 200"
```
<!--
- test: `didSet-calls-superclass-getter`
```swifttest
-> class Superclass {
private var xValue = 12
var x: Int {
get { print("Getter was called"); return xValue }
set { print("Setter was called"); xValue = newValue }
}
}
// This subclass doesn't refer to oldValue in its observer, so the
// superclass's getter is called only once to print the value.
-> class New: Superclass {
override var x: Int {
didSet { print("New value \(x)") }
}
}
let new = New()
new.x = 100
<- Setter was called
<- Getter was called
<- New value 100
// This subclass refers to oldValue in its observer, so the superclass's
// getter is called once before the setter, and again to print the value.
-> class NewAndOld: Superclass {
override var x: Int {
didSet { print("Old value \(oldValue) - new value \(x)") }
}
}
let newAndOld = NewAndOld()
newAndOld.x = 200
<- Getter was called
<- Setter was called
<- Getter was called
<- Old value 12 - new value 200
```
-->
For more information and to see an example of how to use property observers,
see <doc:Properties#Property-Observers>.
<!--
- test: `cant-mix-get-set-and-didSet`
```swifttest
>> struct S {
>> var x: Int {
>> get { print("S getter"); return 12 }
>> set { return }
>> didSet { print("S didSet") }
>> }
>> }
!$ error: 'didSet' cannot be provided together with a getter
!! didSet { print("S didSet") }
!! ^
```
-->
### Type Variable Properties
To declare a type variable property,
mark the declaration with the `static` declaration modifier.
Classes can mark type computed properties with the `class` declaration modifier instead
to allow subclasses to override the superclass’s implementation.
Type properties are discussed in <doc:Properties#Type-Properties>.
> Grammar of a variable declaration:
>
> *variable-declaration* → *variable-declaration-head* *pattern-initializer-list* \
> *variable-declaration* → *variable-declaration-head* *variable-name* *type-annotation* *code-block* \
> *variable-declaration* → *variable-declaration-head* *variable-name* *type-annotation* *getter-setter-block* \
> *variable-declaration* → *variable-declaration-head* *variable-name* *type-annotation* *getter-setter-keyword-block* \
> *variable-declaration* → *variable-declaration-head* *variable-name* *initializer* *willSet-didSet-block* \
> *variable-declaration* → *variable-declaration-head* *variable-name* *type-annotation* *initializer*_?_ *willSet-didSet-block*
>
> *variable-declaration-head* → *attributes*_?_ *declaration-modifiers*_?_ **`var`** \
> *variable-name* → *identifier*
>
> *getter-setter-block* → *code-block* \
> *getter-setter-block* → **`{`** *getter-clause* *setter-clause*_?_ **`}`** \
> *getter-setter-block* → **`{`** *setter-clause* *getter-clause* **`}`** \
> *getter-clause* → *attributes*_?_ *mutation-modifier*_?_ **`get`** *code-block* \
> *setter-clause* → *attributes*_?_ *mutation-modifier*_?_ **`set`** *setter-name*_?_ *code-block* \
> *setter-name* → **`(`** *identifier* **`)`**
>
> *getter-setter-keyword-block* → **`{`** *getter-keyword-clause* *setter-keyword-clause*_?_ **`}`** \
> *getter-setter-keyword-block* → **`{`** *setter-keyword-clause* *getter-keyword-clause* **`}`** \
> *getter-keyword-clause* → *attributes*_?_ *mutation-modifier*_?_ **`get`** \
> *setter-keyword-clause* → *attributes*_?_ *mutation-modifier*_?_ **`set`**
>
> *willSet-didSet-block* → **`{`** *willSet-clause* *didSet-clause*_?_ **`}`** \
> *willSet-didSet-block* → **`{`** *didSet-clause* *willSet-clause*_?_ **`}`** \
> *willSet-clause* → *attributes*_?_ **`willSet`** *setter-name*_?_ *code-block* \
> *didSet-clause* → *attributes*_?_ **`didSet`** *setter-name*_?_ *code-block*
<!--
NOTE: Type annotations are required for computed properties -- the
types of those properties aren't computed/inferred.
-->
## Type Alias Declaration
A *type alias declaration* introduces a named alias of an existing type into your program.
Type alias declarations are declared using the `typealias` keyword and have the following form:
```swift
typealias <#name#> = <#existing type#>
```
After a type alias is declared, the aliased *name* can be used
instead of the *existing type* everywhere in your program.
The *existing type* can be a named type or a compound type.
Type aliases don't create new types;
they simply allow a name to refer to an existing type.
A type alias declaration can use generic parameters
to give a name to an existing generic type. The type alias
can provide concrete types for some or all of the generic parameters
of the existing type.
For example:
```swift
typealias StringDictionary<Value> = Dictionary<String, Value>
// The following dictionaries have the same type.
var dictionary1: StringDictionary<Int> = [:]
var dictionary2: Dictionary<String, Int> = [:]
```
<!--
- test: `typealias-with-generic`
```swifttest
-> typealias StringDictionary<Value> = Dictionary<String, Value>
// The following dictionaries have the same type.
-> var dictionary1: StringDictionary<Int> = [:]
-> var dictionary2: Dictionary<String, Int> = [:]
```
-->
When a type alias is declared with generic parameters, the constraints on those
parameters must match exactly the constraints on the existing type's generic parameters.
For example:
```swift
typealias DictionaryOfInts<Key: Hashable> = Dictionary<Key, Int>
```
<!--
- test: `typealias-with-generic-constraint`
```swifttest
-> typealias DictionaryOfInts<Key: Hashable> = Dictionary<Key, Int>
```
-->
Because the type alias and the existing type can be used interchangeably,
the type alias can't introduce additional generic constraints.
A type alias can forward an existing type's generic parameters
by omitting all generic parameters from the declaration.
For example,
the `Diccionario` type alias declared here
has the same generic parameters and constraints as `Dictionary`.
```swift
typealias Diccionario = Dictionary
```
<!--
- test: `typealias-using-shorthand`
```swifttest
-> typealias Diccionario = Dictionary
```
-->
<!--
Note that the compiler doesn't currently enforce this. For example, this works but shouldn't:
typealias ProvidingMoreSpecificConstraints<T: Comparable & Hashable> = Dictionary<T, Int>
-->
<!--
Things that shouldn't work:
typealias NotRedeclaringSomeOfTheGenericParameters = Dictionary<T, String>
typealias NotRedeclaringAnyOfTheGenericParameters = Dictionary
typealias NotProvidingTheCorrectConstraints<T> = Dictionary<T, Int>
typealias ProvidingMoreSpecificConstraints<T: Comparable & Hashable> = Dictionary<T, Int>
-->
Inside a protocol declaration,
a type alias can give a shorter and more convenient name
to a type that's used frequently.
For example:
```swift
protocol Sequence {
associatedtype Iterator: IteratorProtocol
typealias Element = Iterator.Element
}
func sum<T: Sequence>(_ sequence: T) -> Int where T.Element == Int {
// ...
}
```
<!--
- test: `typealias-in-protocol`
```swifttest
-> protocol Sequence {
associatedtype Iterator: IteratorProtocol
typealias Element = Iterator.Element
}
-> func sum<T: Sequence>(_ sequence: T) -> Int where T.Element == Int {
// ...
>> return 9000
}
```
-->
Without this type alias,
the `sum` function would have to refer to the associated type
as `T.Iterator.Element` instead of `T.Element`.
See also <doc:Declarations#Protocol-Associated-Type-Declaration>.
> Grammar of a type alias declaration:
>
> *typealias-declaration* → *attributes*_?_ *access-level-modifier*_?_ **`typealias`** *typealias-name* *generic-parameter-clause*_?_ *typealias-assignment* \
> *typealias-name* → *identifier* \
> *typealias-assignment* → **`=`** *type*
<!--
Old grammar:
typealias-declaration -> typealias-head typealias-assignment
typealias-head -> ``typealias`` typealias-name type-inheritance-clause-OPT
typealias-name -> identifier
typealias-assignment -> ``=`` type
-->
## Function Declaration
A *function declaration* introduces a function or method into your program.
A function declared in the context of class, structure, enumeration, or protocol
is referred to as a *method*.
Function declarations are declared using the `func` keyword and have the following form:
```swift
func <#function name#>(<#parameters#>) -> <#return type#> {
<#statements#>
}
```
If the function has a return type of `Void`,
the return type can be omitted as follows:
```swift
func <#function name#>(<#parameters#>) {
<#statements#>
}
```
The type of each parameter must be included ---
it can't be inferred.
If you write `inout` in front of a parameter's type,
the parameter can be modified inside the scope of the function.
In-out parameters are discussed in detail
in <doc:Declarations#In-Out-Parameters>, below.
A function declaration whose *statements*
include only a single expression
is understood to return the value of that expression.
This implicit return syntax is considered
only when the expression's type and the function's return type
aren't `Void`
and aren't an enumeration like `Never` that doesn't have any cases.
<!--
As of Swift 5.3,
the only way to make an uninhabited type is to create an empty enum,
so just say that directly instead of using & defining the compiler jargon.
-->
Functions can return multiple values using a tuple type
as the return type of the function.
<!--
TODO: ^-- Add some more here.
-->
A function definition can appear inside another function declaration.
This kind of function is known as a *nested function*.
A nested function is nonescaping if it captures
a value that's guaranteed to never escape ---
such as an in-out parameter ---
or passed as a nonescaping function argument.
Otherwise, the nested function is an escaping function.
For a discussion of nested functions,
see <doc:Functions#Nested-Functions>.
### Parameter Names
Function parameters are a comma-separated list
where each parameter has one of several forms.
The order of arguments in a function call
must match the order of parameters in the function's declaration.
The simplest entry in a parameter list has the following form:
```swift
<#parameter name#>: <#parameter type#>
```
A parameter has a name,
which is used within the function body,
as well as an argument label,
which is used when calling the function or method.
By default,
parameter names are also used as argument labels.
For example:
```swift
func f(x: Int, y: Int) -> Int { return x + y }
f(x: 1, y: 2) // both x and y are labeled
```
<!--
- test: `default-parameter-names`
```swifttest
-> func f(x: Int, y: Int) -> Int { return x + y }
>> let r0 =
-> f(x: 1, y: 2) // both x and y are labeled
>> assert(r0 == 3)
```
-->
<!--
Rewrite the above to avoid bare expressions.
Tracking bug is <rdar://problem/35301593>
-->
You can override the default behavior for argument labels
with one of the following forms:
```swift
<#argument label#> <#parameter name#>: <#parameter type#>
_ <#parameter name#>: <#parameter type#>
```
A name before the parameter name
gives the parameter an explicit argument label,
which can be different from the parameter name.
The corresponding argument must use the given argument label
in function or method calls.
An underscore (`_`) before a parameter name
suppresses the argument label.
The corresponding argument must have no label in function or method calls.
```swift
func repeatGreeting(_ greeting: String, count n: Int) { /* Greet n times */ }
repeatGreeting("Hello, world!", count: 2) // count is labeled, greeting is not
```
<!--
- test: `overridden-parameter-names`
```swifttest
-> func repeatGreeting(_ greeting: String, count n: Int) { /* Greet n times */ }
-> repeatGreeting("Hello, world!", count: 2) // count is labeled, greeting is not
```
-->
### Parameter Modifiers
A *parameter modifier* changes how an argument is passed to the function.
```swift
<#argument label#> <#parameter name#>: <#parameter modifier#> <#parameter type#>
```
To use a parameter modifier,
write `inout`, `borrowing`, or `consuming`
before the argument's type.
```swift
func someFunction(a: inout A, b: consuming B, c: C) { ... }
```
#### In-Out Parameters
By default, function arguments in Swift are passed by value:
Any changes made within the function are not visible in the caller.
To make an in-out parameter instead,
you apply the `inout` parameter modifier.
```swift
func someFunction(a: inout Int) {
a += 1
}
```
When calling a function that includes in-out parameters,
the in-out argument must be prefixed with an ampersand (`&`)
to mark that the function call can change the argument's value.
```swift
var x = 7
someFunction(&x)
print(x) // Prints "8"
```
In-out parameters are passed as follows:
1. When the function is called,
the value of the argument is copied.
2. In the body of the function,
the copy is modified.
3. When the function returns,
the copy's value is assigned to the original argument.
This behavior is known as *copy-in copy-out*
or *call by value result*.
For example,
when a computed property or a property with observers
is passed as an in-out parameter,
its getter is called as part of the function call
and its setter is called as part of the function return.
As an optimization,
when the argument is a value stored at a physical address in memory,
the same memory location is used both inside and outside the function body.
The optimized behavior is known as *call by reference*;
it satisfies all of the requirements
of the copy-in copy-out model
while removing the overhead of copying.
Write your code using the model given by copy-in copy-out,
without depending on the call-by-reference optimization,
so that it behaves correctly with or without the optimization.
Within a function, don't access a value that was passed as an in-out argument,
even if the original value is available in the current scope.
Accessing the original is a simultaneous access of the value,
which violates memory exclusivity.
```swift
var someValue: Int
func someFunction(a: inout Int) {
a += someValue
}
// Error: This causes a runtime exclusivity violation
someFunction(&someValue)
```
For the same reason,
you can't pass the same value to multiple in-out parameters.
```swift
var someValue: Int
func someFunction(a: inout Int, b: inout Int) {
a += b
b += 1
}
// Error: Cannot pass the same value to multiple in-out parameters
someFunction(&someValue, &someValue)
```
For more information about memory safety and memory exclusivity,
see <doc:MemorySafety>.
<!--
When the call-by-reference optimization is in play,
it would happen to do what you want.
But you still shouldn't do that --
as noted above, you're not allowed to depend on
behavioral differences that happen because of call by reference.
-->
A closure or nested function
that captures an in-out parameter must be nonescaping.
If you need to capture an in-out parameter
without mutating it,
use a capture list to explicitly capture the parameter immutably.
```swift
func someFunction(a: inout Int) -> () -> Int {
return { [a] in return a + 1 }
}
```
<!--
- test: `explicit-capture-for-inout`
```swifttest
-> func someFunction(a: inout Int) -> () -> Int {
return { [a] in return a + 1 }
}
>> class C { var x = 100 }
>> let c = C()
>> let f = someFunction(a: &c.x)
>> c.x = 200
>> let r = f()
>> print(r, r == c.x)
<< 101 false
```
-->
If you need to capture and mutate an in-out parameter,
use an explicit local copy,
such as in multithreaded code that ensures
all mutation has finished before the function returns.
```swift
func multithreadedFunction(queue: DispatchQueue, x: inout Int) {
// Make a local copy and manually copy it back.
var localX = x
defer { x = localX }