# Top-Level Code

> Introduce types, operators, variables, and other names and constructs.

- Skill: `tools-only/top-level-code` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/top-level-code`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/top-level-code/raw
- Safety review: pending (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-29
- Page: https://skillmd.com/skills/tools-only/top-level-code

---

# 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:
a file that contains top-level executable code,
a `main.swift` file,
the `main` attribute,
the `NSApplicationMain` attribute,
or the `UIApplicationMain` attribute.

> 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(a: &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(a: &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(a: &someValue, b: &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 }

    // Operate on localX asynchronously, then wait before returning.
    queue.async { someMutatingOperation(&localX) }
    queue.sync {}
}
```

<!--
  - test: `cant-pass-inout-aliasing`

  ```swifttest
  >> import Dispatch
  >> func someMutatingOperation(_ a: inout Int) {}
  -> func multithreadedFunction(queue: DispatchQueue, x: inout Int) {
        // Make a local copy and manually copy it back.
        var localX = x
        defer { x = localX }

        // Operate on localX asynchronously, then wait before returning.
        queue.async { someMutatingOperation(&localX) }
        queue.sync {}
     }
  ```
-->

For more discussion and examples of in-out parameters,
see <doc:Functions#In-Out-Parameters>.

<!--
  - test: `escaping-cant-capture-inout`

  ```swifttest
  -> func outer(a: inout Int) -> () -> Void {
         func inner() {
             a += 1
         }
         return inner
     }
  !$ error: escaping local function captures 'inout' parameter 'a'
  !! return inner
  !! ^
  !$ note: parameter 'a' is declared 'inout'
  !! func outer(a: inout Int) -> () -> Void {
  !! ^
  !$ note: captured here
  !! a += 1
  !! ^
  -> func closure(a: inout Int) -> () -> Void {
         return { a += 1 }
     }
  !$ error: escaping closure captures 'inout' parameter 'a'
  !! return { a += 1 }
  !! ^
  !$ note: parameter 'a' is declared 'inout'
  !! func closure(a: inout Int) -> () -> Void {
  !! ^
  !$ note: captured here
  !! return { a += 1 }
  !! ^
  ```
-->

#### Borrowing and Consuming Parameters

By default, Swift uses a set of rules
to automatically manage object lifetime across function calls,
copying values when required.
The default rules are designed to minimize overhead in most cases ---
if you want more specific control,
you can apply the `borrowing` or `consuming` parameter modifier.
In this case,
use `copy` to explicitly mark copy operations.
In addition,
values of a noncopyable type must be passed as either borrowing or consuming.

Regardless of whether you use the default rules,
Swift guarantees that object lifetime and
ownership are correctly managed in all cases.
These parameter modifiers impact only the relative efficiency
of particular usage patterns, not correctness.

<!--
TODO: Describe the default rules.
Essentially, inits and property setters are consuming,
and everything else is borrowing.
Where are copies implicitly inserted?
-->

The `borrowing` modifier indicates that the function
does not keep the parameter's value.
In this case, the caller maintains ownership of the object
and the responsibility for the object's lifetime.
Using `borrowing` minimizes overhead when the function
uses the object only transiently.

```swift
// `isLessThan` does not keep either argument
func isLessThan(lhs: borrowing A, rhs: borrowing A) -> Bool {
    ...
}
```

If the function needs to keep the parameter's value
for example, by storing it in a global variable ---
you use `copy` to explicitly copy that value.

```swift
// As above, but this `isLessThan` also wants to record the smallest value
func isLessThan(lhs: borrowing A, rhs: borrowing A) -> Bool {
    if lhs < storedValue {
        storedValue = copy lhs
    } else if rhs < storedValue {
        storedValue = copy rhs
    }
    return lhs < rhs
}
```

Conversely,
the `consuming` parameter modifier indicates
that the function takes ownership of the value,
accepting responsibility for either storing or destroying it
before the function returns.

```swift
// `store` keeps its argument, so mark it `consuming`
func store(a: consuming A) {
    someGlobalVariable = a
}
```

Using `consuming` minimizes overhead when the caller no longer
needs to use the object after the function call.

```swift
// Usually, this is the last thing you do with a value
store(a: value)
```

If you keep using a copyable object after the function call,
the compiler automatically makes a copy of that object
before the function call.

```swift
// The compiler inserts an implicit copy here
store(a: someValue)  // This function consumes someValue
print(someValue)  // This uses the copy of someValue
```

Unlike `inout`, neither `borrowing` nor
`consuming` parameters require any special
notation when you call the function:

```swift
func someFunction(a: borrowing A, b: consuming B) { ... }

someFunction(a: someA, b: someB)
```

The explicit use of either `borrowing` or `consuming`
indicates your intention to more tightly control
the overhead of runtime ownership management.
Because copies can cause unexpected runtime ownership
operations,
parameters marked with either of these
modifiers cannot be copied unless you
use an explicit `copy` keyword:

```swift
func borrowingFunction1(a: borrowing A) {
    // Error: Cannot implicitly copy a
    // This assignment requires a copy because
    // `a` is only borrowed from the caller.
    someGlobalVariable = a
}

func borrowingFunction2(a: borrowing A) {
    // OK: Explicit copying works
    someGlobalVariable = copy a
}

func consumingFunction1(a: consuming A) {
    // Error: Cannot implicitly copy a
    // This assignment requires a copy because
    // of the following `print`
    someGlobalVariable = a
    print(a)
}

func consumingFunction2(a: consuming A) {
    // OK: Explicit copying works regardless
    someGlobalVariable = copy a
    print(a)
}

func consumingFunction3(a: consuming A) {
    // OK: No copy needed here because this is the last use
    someGlobalVariable = a
}
```

<!--
  TODO: `borrowing` and `consuming` keywords with noncopyable argument types
-->
<!--
  TODO: Any change of parameter modifier is ABI-breaking
-->

### Special Kinds of Parameters

Parameters can be ignored,
take a variable number of values,
and provide default values
using the following forms:

```swift
_ : <#parameter type#>
<#parameter name#>: <#parameter type#>...
<#parameter name#>: <#parameter type#> = <#default argument value#>
```

An underscore (`_`) parameter
is explicitly ignored and can't be accessed within the body of the function.

A parameter with a base type name followed immediately by three dots (`...`)
is understood as a variadic parameter.
A parameter that immediately follows a variadic parameter
must have an argument label.
A function can have multiple variadic parameters.
A variadic parameter is treated as an array that contains elements of the base type name.
For example, the variadic parameter `Int...` is treated as `[Int]`.
For an example that uses a variadic parameter,
see <doc:Functions#Variadic-Parameters>.

A parameter with an equal sign (`=`) and an expression after its type
is understood to have a default value of the given expression.
The given expression is evaluated when the function is called.
If the parameter is omitted when calling the function,
the 

…(truncated)
