# Statements

Group expressions and control the flow of execution.

In Swift, there are three kinds of statements: simple statements, compiler control statements,
and control flow statements.
Simple statements are the most common and consist of either an expression or a declaration.
Compiler control statements allow the program to change aspects of the compiler's behavior
and include a conditional compilation block and a line control statement.

Control flow statements are used to control the flow of execution in a program.
There are several types of control flow statements in Swift, including
loop statements, branch statements, and control transfer statements.
Loop statements allow a block of code to be executed repeatedly,
branch statements allow a certain block of code to be executed
only when certain conditions are met,
and control transfer statements provide a way to alter the order in which code is executed.
In addition, Swift provides a `do` statement to introduce scope,
and catch and handle errors,
and a `defer` statement for running cleanup actions just before the current scope exits.

A semicolon (`;`) can optionally appear after any statement
and is used to separate multiple statements if they appear on the same line.

> Grammar of a statement:
>
> *statement* → *expression* **`;`**_?_ \
> *statement* → *declaration* **`;`**_?_ \
> *statement* → *loop-statement* **`;`**_?_ \
> *statement* → *branch-statement* **`;`**_?_ \
> *statement* → *labeled-statement* **`;`**_?_ \
> *statement* → *control-transfer-statement* **`;`**_?_ \
> *statement* → *defer-statement* **`;`**_?_ \
> *statement* → *do-statement* **`;`**_?_ \
> *statement* → *compiler-control-statement* \
> *statements* → *statement* *statements*_?_

<!--
  NOTE: Removed semicolon-statement as syntactic category,
  because, according to Doug, they're not really statements.
  For example, you can't have
      if foo { ; }
  but you should be able to if it's truly considered a statement.
  The semicolon isn't even required for the compiler; we just added
  rules that require them in some places to enforce a certain amount
  of readability.
-->

## Loop Statements

Loop statements allow a block of code to be executed repeatedly,
depending on the conditions specified in the loop.
Swift has three loop statements:
a `for`-`in` statement,
a `while` statement,
and a `repeat`-`while` statement.

Control flow in a loop statement can be changed by a `break` statement
and a `continue` statement and is discussed in [Break Statement](Statements.md#Break-Statement) and
[Continue Statement](Statements.md#Continue-Statement) below.

> Grammar of a loop statement:
>
> *loop-statement* → *for-in-statement* \
> *loop-statement* → *while-statement* \
> *loop-statement* → *repeat-while-statement*

### For-In Statement

A `for`-`in` statement allows a block of code to be executed
once for each item in a collection (or any type)
that conforms to the
[`Sequence`](https://developer.apple.com/documentation/swift/sequence) protocol.

A `for`-`in` statement has the following form:

```swift
for <#item#> in <#collection#> {
   <#statements#>
}
```

The `makeIterator()` method is called on the *collection* expression
to obtain a value of an iterator type --- that is,
a type that conforms to the
[`IteratorProtocol`](https://developer.apple.com/documentation/swift/iteratorprotocol) protocol.
The program begins executing a loop
by calling the `next()` method on the iterator.
If the value returned isn't `nil`,
it's assigned to the *item* pattern,
the program executes the *statements*,
and then continues execution at the beginning of the loop.
Otherwise, the program doesn't perform assignment or execute the *statements*,
and it's finished executing the `for`-`in` statement.

> Grammar of a for-in statement:
>
> *for-in-statement* → **`for`** **`case`**_?_ *pattern* **`in`** *expression* *where-clause*_?_ *code-block*

### While Statement

A `while` statement allows a block of code to be executed repeatedly,
as long as a condition remains true.

A `while` statement has the following form:

```swift
while <#condition#> {
   <#statements#>
}
```

A `while` statement is executed as follows:

1. The *condition* is evaluated.

   If `true`, execution continues to step 2.
   If `false`, the program is finished executing the `while` statement.
2. The program executes the *statements*, and execution returns to step 1.

Because the value of the *condition* is evaluated before the *statements* are executed,
the *statements* in a `while` statement can be executed zero or more times.

The value of the *condition*
must be of type `Bool` or a type bridged to `Bool`.
The condition can also be an optional binding declaration,
as discussed in [Optional Binding](../LanguageGuide/TheBasics.md#Optional-Binding).

> Grammar of a while statement:
>
> *while-statement* → **`while`** *condition-list* *code-block*
>
> *condition-list* → *condition* | *condition* **`,`** *condition-list* \
> *condition* → *expression* | *availability-condition* | *case-condition* | *optional-binding-condition*
>
> *case-condition* → **`case`** *pattern* *initializer* \
> *optional-binding-condition* → **`let`** *pattern* *initializer*_?_ | **`var`** *pattern* *initializer*_?_

### Repeat-While Statement

A `repeat`-`while` statement allows a block of code to be executed one or more times,
as long as a condition remains true.

A `repeat`-`while` statement has the following form:

```swift
repeat {
   <#statements#>
} while <#condition#>
```

A `repeat`-`while` statement is executed as follows:

1. The program executes the *statements*,
   and execution continues to step 2.
2. The *condition* is evaluated.

   If `true`, execution returns to step 1.
   If `false`, the program is finished executing the `repeat`-`while` statement.

Because the value of the *condition* is evaluated after the *statements* are executed,
the *statements* in a `repeat`-`while` statement are executed at least once.

The value of the *condition*
must be of type `Bool` or a type bridged to `Bool`.

> Grammar of a repeat-while statement:
>
> *repeat-while-statement* → **`repeat`** *code-block* **`while`** *expression*

## Branch Statements

Branch statements allow the program to execute certain parts of code
depending on the value of one or more conditions.
The values of the conditions specified in a branch statement
control how the program branches and, therefore, what block of code is executed.
Swift has three branch statements:
an `if` statement, a `guard` statement, and a `switch` statement.

Control flow in an `if` statement or a `switch` statement can be changed by a `break` statement
and is discussed in [Break Statement](Statements.md#Break-Statement) below.

> Grammar of a branch statement:
>
> *branch-statement* → *if-statement* \
> *branch-statement* → *guard-statement* \
> *branch-statement* → *switch-statement*

### If Statement

An `if` statement is used for executing code
based on the evaluation of one or more conditions.

There are two basic forms of an `if` statement.
In each form, the opening and closing braces are required.

The first form allows code to be executed only when a condition is true
and has the following form:

```swift
if <#condition#> {
   <#statements#>
}
```

The second form of an `if` statement provides an additional *else clause*
(introduced by the `else` keyword)
and is used for executing one part of code when the condition is true
and another part of code when the same condition is false.
When a single else clause is present, an `if` statement has the following form:

```swift
if <#condition#> {
   <#statements to execute if condition is true#>
} else {
   <#statements to execute if condition is false#>
}
```

The else clause of an `if` statement can contain another `if` statement
to test more than one condition.
An `if` statement chained together in this way has the following form:

```swift
if <#condition 1#> {
   <#statements to execute if condition 1 is true#>
} else if <#condition 2#> {
   <#statements to execute if condition 2 is true#>
} else {
   <#statements to execute if both conditions are false#>
}
```

The value of any condition in an `if` statement
must be of type `Bool` or a type bridged to `Bool`.
The condition can also be an optional binding declaration,
as discussed in [Optional Binding](../LanguageGuide/TheBasics.md#Optional-Binding).

> Grammar of an if statement:
>
> *if-statement* → **`if`** *condition-list* *code-block* *else-clause*_?_ \
> *else-clause* → **`else`** *code-block* | **`else`** *if-statement*

### Guard Statement

A `guard` statement is used to transfer program control out of a scope
if one or more conditions aren't met.

A `guard` statement has the following form:

```swift
guard <#condition#> else {
   <#statements#>
}
```

The value of any condition in a `guard` statement
must be of type `Bool` or a type bridged to `Bool`.
The condition can also be an optional binding declaration,
as discussed in [Optional Binding](../LanguageGuide/TheBasics.md#Optional-Binding).

Any constants or variables assigned a value
from an optional binding declaration in a `guard` statement condition
can be used for the rest of the guard statement's enclosing scope.

The `else` clause of a `guard` statement is required,
and must either call a function with the `Never` return type
or transfer program control outside the guard statement's enclosing scope
using one of the following statements:

- `return`
- `break`
- `continue`
- `throw`

Control transfer statements are discussed in [Control Transfer Statements](Statements.md#Control-Transfer-Statements) below.
For more information on functions with the `Never` return type,
see [Functions that Never Return](Declarations.md#Functions-that-Never-Return).

> Grammar of a guard statement:
>
> *guard-statement* → **`guard`** *condition-list* **`else`** *code-block*

### Switch Statement

A `switch` statement allows certain blocks of code to be executed
depending on the value of a control expression.

A `switch` statement has the following form:

```swift
switch <#control expression#> {
case <#pattern 1#>:
    <#statements#>
case <#pattern 2#> where <#condition#>:
    <#statements#>
case <#pattern 3#> where <#condition#>,
    <#pattern 4#> where <#condition#>:
    <#statements#>
default:
    <#statements#>
}
```

The *control expression* of the `switch` statement is evaluated
and then compared with the patterns specified in each case.
If a match is found,
the program executes the *statements* listed within the scope of that case.
The scope of each case can't be empty.
As a result, you must include at least one statement
following the colon (`:`) of each case label. Use a single `break` statement
if you don't intend to execute any code in the body of a matched case.

The values of expressions your code can branch on are very flexible. For example,
in addition to the values of scalar types, such as integers and characters,
your code can branch on the values of any type, including floating-point numbers, strings,
tuples, instances of custom classes, and optionals.
The value of the *control expression* can even be matched to the value of a case in an enumeration
and checked for inclusion in a specified range of values.
For examples of how to use these various types of values in `switch` statements,
see [Switch](../LanguageGuide/ControlFlow.md#Switch) in [Control Flow](../LanguageGuide/ControlFlow.md).

A `switch` case can optionally contain a `where` clause after each pattern.
A *where clause* is introduced by the `where` keyword followed by an expression,
and is used to provide an additional condition
before a pattern in a case is considered matched to the *control expression*.
If a `where` clause is present, the *statements* within the relevant case
are executed only if the value of the *control expression*
matches one of the patterns of the case and the expression of the `where` clause evaluates to `true`.
For example, a *control expression* matches the case in the example below
only if it's a tuple that contains two elements of the same value, such as `(1, 1)`.

```swift
case let (x, y) where x == y:
```

As the above example shows, patterns in a case can also bind constants
using the `let` keyword (they can also bind variables using the `var` keyword).
These constants (or variables) can then be referenced in a corresponding `where` clause
and throughout the rest of the code within the scope of the case.
If the case contains multiple patterns that match the control expression,
all of the patterns must contain the same constant or variable bindings,
and each bound variable or constant must have the same type
in all of the case's patterns.

<!--
  The discussion above about multi-pattern cases
  matches discussion of multi-pattern catch under Do Statement.
-->

A `switch` statement can also include a default case, introduced by the `default` keyword.
The code within a default case is executed only if no other cases match the control expression.
A `switch` statement can include only one default case,
which must appear at the end of the `switch` statement.

Although the actual execution order of pattern-matching operations,
and in particular the evaluation order of patterns in cases, is unspecified,
pattern matching in a `switch` statement behaves
as if the evaluation is performed in source order --- that is,
the order in which they appear in source code.
As a result, if multiple cases contain patterns that evaluate to the same value,
and thus can match the value of the control expression,
the program executes only the code within the first matching case in source order.

#### Switch Statements Must Be Exhaustive

In Swift,
every possible value of the control expression’s type
must match the value of at least one pattern of a case.
When this simply isn’t feasible
(for example, when the control expression’s type is `Int`),
you can include a default case to satisfy the requirement.

#### Switching Over Future Enumeration Cases

A *nonfrozen enumeration* is a special kind of enumeration
that may gain new enumeration cases in the future ---
even after you compile and ship an app.
Switching over a nonfrozen enumeration requires extra consideration.
When a library's authors mark an enumeration as nonfrozen,
they reserve the right to add new enumeration cases,
and any code that interacts with that enumeration
*must* be able to handle those future cases without being recompiled.
Code that's compiled in library evolution mode,
code in the Swift standard library,
Swift overlays for Apple frameworks,
and C and Objective-C code can declare nonfrozen enumerations.
For information about frozen and nonfrozen enumerations,
see [frozen](Attributes.md#frozen).

When switching over a nonfrozen enumeration value,
you always need to include a default case,
even if every case of the enumeration already has a corresponding switch case.
You can apply the `@unknown` attribute to the default case,
which indicates that the default case should match only enumeration cases
that are added in the future.
Swift produces a warning
if the default case matches
any enumeration case that's known at compile time.
This future warning informs you that the library author
added a new case to the enumeration
that doesn't have a corresponding switch case.

The following example switches over all three existing cases of
the Swift standard library's [`Mirror.AncestorRepresentation`](https://developer.apple.com/documentation/swift/mirror/ancestorrepresentation)
enumeration.
If you add additional cases in the future,
the compiler generates a warning to indicate
that you need to update the switch statement
to take the new cases into account.

```swift
let representation: Mirror.AncestorRepresentation = .generated
switch representation {
case .customized:
    print("Use the nearest ancestor’s implementation.")
case .generated:
    print("Generate a default mirror for all ancestor classes.")
case .suppressed:
    print("Suppress the representation of all ancestor classes.")
@unknown default:
    print("Use a representation that was unknown when this code was compiled.")
}
// Prints "Generate a default mirror for all ancestor classes."
```

#### Execution Does Not Fall Through Cases Implicitly

After the code within a matched case has finished executing,
the program exits from the `switch` statement.
Program execution doesn't continue or "fall through" to the next case or default case.
That said, if you want execution to continue from one case to the next,
explicitly include a `fallthrough` statement,
which simply consists of the `fallthrough` keyword,
in the case from which you want execution to continue.
For more information about the `fallthrough` statement,
see [Fallthrough Statement](Statements.md#Fallthrough-Statement) below.

> Grammar of a switch statement:
>
> *switch-statement* → **`switch`** *expression* **`{`** *switch-cases*_?_ **`}`** \
> *switch-cases* → *switch-case* *switch-cases*_?_ \
> *switch-case* → *case-label* *statements* \
> *switch-case* → *default-label* *statements* \
> *switch-case* → *conditional-switch-case*
>
> *case-label* → *attributes*_?_ **`case`** *case-item-list* **`:`** \
> *case-item-list* → *pattern* *where-clause*_?_ | *pattern* *where-clause*_?_ **`,`** *case-item-list* \
> *default-label* → *attributes*_?_ **`default`** **`:`**
>
> *where-clause* → **`where`** *where-expression* \
> *where-expression* → *expression*
>
> *conditional-switch-case* → *switch-if-directive-clause* *switch-elseif-directive-clauses*_?_ *switch-else-directive-clause*_?_ *endif-directive* \
> *switch-if-directive-clause* → *if-directive* *compilation-condition* *switch-cases*_?_ \
> *switch-elseif-directive-clauses* → *elseif-directive-clause* *switch-elseif-directive-clauses*_?_ \
> *switch-elseif-directive-clause* → *elseif-directive* *compilation-condition* *switch-cases*_?_ \
> *switch-else-directive-clause* → *else-directive* *switch-cases*_?_

<!--
  The grammar above uses attributes-OPT to match what's used
  in all other places where attributes are allowed,
  although as of Swift 4.2 only a single attribute (@unknown) is allowed.
-->

## Labeled Statement

You can prefix a loop statement, an `if` statement, a `switch` statement,
or a `do` statement with a *statement label*,
which consists of the name of the label followed immediately by a colon (:).
Use statement labels with `break` and `continue` statements to be explicit
about how you want to change control flow in a loop statement or a `switch` statement,
as discussed in [Break Statement](Statements.md#Break-Statement) and
[Continue Statement](Statements.md#Continue-Statement) below.

The scope of a labeled statement is the entire statement following the statement label.
You can nest labeled statements, but the name of each statement label must be unique.

For more information and to see examples
of how to use statement labels,
see [Labeled Statements](../LanguageGuide/ControlFlow.md#Labeled-Statements) in [Control Flow](../LanguageGuide/ControlFlow.md).

> Grammar of a labeled statement:
>
> *labeled-statement* → *statement-label* *loop-statement* \
> *labeled-statement* → *statement-label* *if-statement* \
> *labeled-statement* → *statement-label* *switch-statement* \
> *labeled-statement* → *statement-label* *do-statement*
>
> *statement-label* → *label-name* **`:`** \
> *label-name* → *identifier*

## Control Transfer Statements

Control transfer statements can change the order in which code in your program is executed
by unconditionally transferring program control from one piece of code to another.
Swift has five control transfer statements: a `break` statement, a `continue` statement,
a `fallthrough` statement, a `return` statement, and a `throw` statement.

> Grammar of a control transfer statement:
>
> *control-transfer-statement* → *break-statement* \
> *control-transfer-statement* → *continue-statement* \
> *control-transfer-statement* → *fallthrough-statement* \
> *control-transfer-statement* → *return-statement* \
> *control-transfer-statement* → *throw-statement*

### Break Statement

A `break` statement ends program execution of a loop,
an `if` statement, or a `switch` statement.
A `break` statement can consist of only the `break` keyword,
or it can consist of the `break` keyword followed by the name of a statement label,
as shown below.

```swift
break
break <#label name#>
```

When a `break` statement is followed by the name of a statement label,
it ends program execution of the loop,
`if` statement, or `switch` statement named by that label.

When a `break` statement isn't followed by the name of a statement label,
it ends program execution of the `switch` statement or the innermost enclosing loop
statement in which it occurs.
You can't use an unlabeled `break` statement to break out of an `if` statement.

In both cases, program control is then transferred to the first line
of code following the enclosing loop or `switch` statement, if any.

For examples of how to use a `break` statement,
see [Break](../LanguageGuide/ControlFlow.md#Break) and [Labeled Statements](../LanguageGuide/ControlFlow.md#Labeled-Statements)
in [Control Flow](../LanguageGuide/ControlFlow.md).

> Grammar of a break statement:
>
> *break-statement* → **`break`** *label-name*_?_

### Continue Statement

A `continue` statement ends program execution of the current iteration of a loop
statement but doesn't stop execution of the loop statement.
A `continue` statement can consist of only the `continue` keyword,
or it can consist of the `continue` keyword followed by the name of a statement label,
as shown below.

```swift
continue
continue <#label name#>
```

When a `continue` statement is followed by the name of a statement label,
it ends program execution of the current iteration
of the loop statement named by that label.

When a `continue` statement isn't followed by the name of a statement label,
it ends program execution of the current iteration
of the innermost enclosing loop statement in which it occurs.

In both cases, program control is then transferred to the condition
of the enclosing loop statement.

In a `for` statement,
the increment expression is still evaluated after the `continue` statement is executed,
because the increment expression is evaluated after the execution of the loop's body.

For examples of how to use a `continue` statement,
see [Continue](../LanguageGuide/ControlFlow.md#Continue) and [Labeled Statements](../LanguageGuide/ControlFlow.md#Labeled-Statements)
in [Control Flow](../LanguageGuide/ControlFlow.md).

> Grammar of a continue statement:
>
> *continue-statement* → **`continue`** *label-name*_?_

### Fallthrough Statement

A `fallthrough` statement consists of the `fallthrough` keyword
and occurs only in a case block of a `switch` statement.
A `fallthrough` statement causes program execution to continue
from one case in a `switch` statement to the next case.
Program execution continues to the next case
even if the patterns of the case label don't match
the value of the `switch` statement's control expression.

A `fallthrough` statement can appear anywhere inside a `switch` statement,
not just as the last statement of a case block,
but it can't be used in the final case block.
It also can't transfer control into a case block
whose pattern contains value binding patterns.

For an example of how to use a `fallthrough` statement in a `switch` statement,
see [Control Transfer Statements](../LanguageGuide/ControlFlow.md#Control-Transfer-Statements)
in [Control Flow](../LanguageGuide/ControlFlow.md).

> Grammar of a fallthrough statement:
>
> *fallthrough-statement* → **`fallthrough`**

### Return Statement

A `return` statement occurs in the body of a function or method definition
and causes program execution to return to the calling function or method.
Program execution continues at the point immediately following the function or method call.

A `return` statement can consist of only the `return` keyword,
or it can consist of the `return` keyword followed by an expression, as shown below.

```swift
return
return <#expression#>
```

When a `return` statement is followed by an expression,
the value of the expression is returned to the calling function or method.
If the value of the expression doesn't match the value of the return type
declared in the function or method declaration,
the expression's value is converted to the return type
before it's returned to the calling function or method.

> Note: As described in [Failable Initializers](Declarations.md#Failable-Initializers), a special form of the `return` statement (`return nil`)
> can be used in a failable initializer to indicate initialization failure.

<!--
  TODO: Discuss how the conversion takes place and what is allowed to be converted
  in the (yet to be written) chapter on subtyping and type conversions.
-->

When a `return` statement isn't followed by an expression,
it can be used only to return from a function or method that doesn't return a value
(that is, when the return type of the function or method is `Void` or `()`).

> Grammar of a return statement:
>
> *return-statement* → **`return`** *expression*_?_

### Throw Statement

A `throw` statement occurs in the body of a throwing function or method,
or in the body of a closure expression whose type is marked with the `throws` keyword.

A `throw` statement causes a program to end execution of the current scope
and begin error propagation to its enclosing scope.
The error that's thrown continues to propagate until it's handled by a `catch` clause
of a `do` statement.

A `throw` statement consists of the `throw` keyword
followed by an expression, as shown below.

```swift
throw <#expression#>
```

The value of the *expression* must have a type that conforms to
the `Error` protocol.
If the `do` statement or function that contains the `throw` statement
declares the type of errors it throws,
the value of the *expression* must be an instance of that type.

For an example of how to use a `throw` statement,
see [Propagating Errors Using Throwing Functions](../LanguageGuide/ErrorHandling.md#Propagating-Errors-Using-Throwing-Functions)
in [Error Handling](../LanguageGuide/ErrorHandling.md).

> Grammar of a throw statement:
>
> *throw-statement* → **`throw`** *expression*

## Defer Statement

A `defer` statement is used for executing code
just before transferring program control outside of the scope
that the `defer` statement appears in.

A `defer` statement has the following form:

```swift
defer {
    <#statements#>
}
```

The statements within the `defer` statement are executed
no matter how program control is transferred.
This means that a `defer` statement can be used, for example,
to perform manual resource management such as closing file descriptors,
and to perform actions that need to happen even if an error is thrown.

The *statements* in the `defer` statement
are executed at the end of the scope that encloses the `defer` statement.

```swift
func f(x: Int) {
  defer { print("First defer") }

  if x < 10 {
    defer { print("Second defer") }
    print("End of if")
  }

  print("End of function")
}
f(x: 5)
// Prints "End of if".
// Prints "Second defer".
// Prints "End of function".
// Prints "First defer".
```

<!--
  ```swifttest
  -> func f(x: Int) {
    defer { print("First defer") }

    if x < 10 {
      defer { print("Second defer") }
      print("End of if")
    }

    print("End of function")
  }
  f(x: 5)
  <- End of if
  <- Second defer
  <- End of function
  <- First defer
  ```
-->

In the code above,
the `defer` in the `if` statement
executes before the `defer` declared in the function `f`
because the scope of the `if` statement ends
before the scope of the function.

If multiple `defer` statements appear in the same scope,
the order they appear is the reverse of the order they're executed.
Executing the last `defer` statement in a given scope first
means that statements inside that last `defer` statement
can refer to resources that will be cleaned up by other `defer` statements.

```swift
func f() {
    defer { print("First defer") }
    defer { print("Second defer") }
    print("End of function")
}
f()
// Prints "End of function".
// Prints "Second defer".
// Prints "First defer".
```

<!--
  ```swifttest
  -> func f() {
         defer { print("First defer") }
         defer { print("Second defer") }
         print("End of function")
     }
     f()
  <- End of function
  <- Second defer
  <- First defer
  ```
-->

The statements in the `defer` statement can't
transfer program control outside of the `defer` statement.

> Grammar of a defer statement:
>
> *defer-statement* → **`defer`** *code-block*

## Do Statement

The `do` statement is used to introduce a new scope
and can optionally contain one or more `catch` clauses,
which contain patterns that match against defined error conditions.
Variables and constants declared in the scope of a `do` statement
can be accessed only within that scope.

A `do` statement in Swift is similar to
curly braces (`{}`) in C used to delimit a code block,
and doesn't incur a performance cost at runtime.

A `do` statement has the following form:

```swift
do {
    try <#expression#>
    <#statements#>
} catch <#pattern 1#> {
    <#statements#>
} catch <#pattern 2#> where <#condition#> {
    <#statements#>
} catch <#pattern 3#>, <#pattern 4#> where <#condition#> {
    <#statements#>
} catch {
    <#statements#>
}
```

A `do` statement can optionally specify the type of error it throws,
which has the following form:

```swift
do throws(<#type#>) {
    try <#expression#>
} catch <#pattern> {
    <#statements#>
} catch {
    <#statements#>
}
```

If the `do` statement includes a `throws` clause,
the `do` block can throw errors of only the specified *type*.
The *type* must be
a concrete type that conforms to the `Error` protocol,
an opaque type that conforms to the `Error` protocol,
or the boxed protocol type `any Error`.
If the `do` statement doesn't specify the type of error it throws,
Swift infers the error type as follows:

- If every `throws` statement and `try` expression in the `do` code block
  is nested inside of an exhaustive error-handling mechanism,
  then Swift infers that the `do` statement is nonthrowing.

- If the `do` code block contains code that throws
  errors of only a single type
  outside of exhaustive error handling,
  other than throwing `Never`,
  then Swift infers that the `do` statement throws that concrete error type.

- If the `do` code block contains code that throws
  errors of more than a single type
  outside of exhaustive error handling,
  then Swift infers that the `do` statement throws `any Error`.

For more information about working with errors that have explicit types,
see [Specifying the Error Type](../LanguageGuide/ErrorHandling.md#Specifying-the-Error-Type).

If any statement in the `do` code block throws an error,
program control is transferred
to the first `catch` clause whose pattern matches the error.
If none of the clauses match,
the error propagates to the surrounding scope.
If an error is unhandled at the top level,
program execution stops with a runtime error.

Like a `switch` statement,
the compiler attempts to infer whether `catch` clauses are exhaustive.
If such a determination can be made, the error is considered handled.
Otherwise, the error can propagate out of the containing scope,
which means
the error must be handled by an enclosing `catch` clause
or the containing function must be declared with `throws`.

A `catch` clause that has multiple patterns
matches the error if any of its patterns match the error.
If a `catch` clause contains multiple patterns,
all of the patterns must contain the same constant or variable bindings,
and each bound variable or constant must have the same type
in all of the `catch` clause's patterns.

<!--
  The discussion above of multi-pattern catch
  matches the discussion of multi-pattern case under Switch Statement.
-->

To ensure that an error is handled,
use a `catch` clause with a pattern that matches all errors,
such as a wildcard pattern (`_`).
If a `catch` clause doesn't specify a pattern,
the `catch` clause matches and binds any error to a local constant named `error`.
For more information about the patterns you can use in a `catch` clause,
see [Patterns](Patterns.md).

To see an example of how to use a `do` statement with several `catch` clauses,
see [Handling Errors](../LanguageGuide/ErrorHandling.md#Handling-Errors).

> Grammar of a do statement:
>
> *do-statement* → **`do`** *throws-clause*_?_ *code-block* *catch-clauses*_?_ \
> *catch-clauses* → *catch-clause* *catch-clauses*_?_ \
> *catch-clause* → **`catch`** *catch-pattern-list*_?_ *code-block* \
> *catch-pattern-list* → *catch-pattern* | *catch-pattern* **`,`** *catch-pattern-list* \
> *catch-pattern* → *pattern* *where-clause*_?_

## Compiler Control Statements

Compiler control statements allow the program to change aspects of the compiler's behavior.
Swift has three compiler control statements:
a conditional compilation block
a line control statement,
and a compile-time diagnostic statement.

> Grammar of a compiler control statement:
>
> *compiler-control-statement* → *conditional-compilation-block* \
> *compiler-control-statement* → *line-control-statement* \
> *compiler-control-statement* → *diagnostic-statement*

### Conditional Compilation Block

A conditional compilation block allows code to be conditionally compiled
depending on the value of one or more compilation conditions.

Every conditional compilation block begins with the `#if` compilation directive
and ends with the `#endif` compilation directive.
A simple conditional compilation block has the following form:

```swift
#if <#compilation condition#>
    <#statements#>
#endif
```

Unlike the condition of an `if` statement,
the *compilation condition* is evaluated at compile time.
As a result,
the *statements* are compiled and executed only if the *compilation condition*
evaluates to `true` at compile time.

The *compilation condition* can include the `true` and `false` Boolean literals,
an identifier used with the `-D` command line flag, or any of the platform
conditions listed in the table below.

| Platform condition | Valid arguments |
| ------------------ | --------------- |
| `os()` | `macOS`, `iOS`, `watchOS`, `tvOS`, `visionOS`, `Linux`, `Windows` |
| `arch()` | `arm`, `arm64`, `i386`, `wasm32`, `x86_64`, |
| `swift()` | `>=` or `<` followed by a version number |
| `compiler()` | `>=` or `<` followed by a version number |
| `canImport()` | A module name |
| `targetEnvironment()` | `simulator`, `macCatalyst` |

<!--
  The lists above match <https://www.swift.org/platform-support/>
  and include only platforms with *official* support.
  For the full list of operating systems and architectures,
  including those with unofficial or experimental support,
  see the values of
  SupportedConditionalCompilationOSs and SupportedConditionalCompilationArches
  in the file lib/Basic/LangOptions.cpp.
  The compiler also accepts pretty much any string --
  for example "#if os(toaster)" compiles just fine,
  but Swift doesn't actually support running on a toaster oven --
  so don't rely on that when checking possible os/arch values.
-->

<!--
  The target environment "UIKitForMac"
  is understood by the compiler as a synonym for "macCatalyst",
  but that spelling is marked "Must be removed" outside of a few places,
  so it's omitted from the table above.
-->

The version number for the `swift()` and `compiler()` platform conditions
consists of a major number, optional minor number, optional patch number, and so on,
with a dot (`.`) separating each part of the version number.
There must not be whitespace between the comparison operator and the version number.
The version for `compiler()` is the compiler version,
regardless of the Swift version setting passed to the compiler.
The version for `swift()` is the language version currently being compiled.
For example, if you compile your code using the Swift 5 compiler in Swift 4.2 mode,
the compiler version is 5 and the language version is 4.2.
With those settings,
the following code prints all three messages:

```swift
#if compiler(>=5)
print("Compiled with the Swift 5 compiler or later")
#endif
#if swift(>=4.2)
print("Compiled in Swift 4.2 mode or later")
#endif
#if compiler(>=5) && swift(<5)
print("Compiled with the Swift 5 compiler or later in a Swift mode earlier than 5")
#endif
// Prints "Compiled with the Swift 5 compiler or later".
// Prints "Compiled in Swift 4.2 mode or later".
// Prints "Compiled with the Swift 5 compiler or later in a Swift mode earlier than 5".
```

<!--
  ```swifttest
  -> #if compiler(>=5)
     print("Compiled with the Swift 5 compiler or later")
     #endif
     #if swift(>=4.2)
     print("Compiled in Swift 4.2 mode or later")
     #endif
     #if compiler(>=5) && swift(<5)
     print("Compiled with the Swift 5 compiler or later in a Swift mode earlier than 5")
     #endif
  <- Compiled with the Swift 5 compiler or later
  <- Compiled in Swift 4.2 mode or later
  // Prints "Compiled with the Swift 5 compiler or later in a Swift mode earlier than 5".
  ```
-->

<!--
  That testcode is cheating by explicitly printing the third line of output,
  since it's not actually running in Swift 4.2 mode.
-->

The argument for the `canImport()` platform condition
is the name of a module that may not be present on all platforms.
The module can include periods (`.`) in its name.
This condition tests whether it's possible to import the module,
but doesn't actually import it.
If the module is present, the platform condition returns `true`;
otherwise, it returns `false`.

The `targetEnvironment()` platform condition
returns `true` when code is being compiled for the specified environment;
otherwise, it returns `false`.

> Note: The `arch(arm)` platform condition doesn't return `true` for ARM 64 devices.
> The `arch(i386)` platform condition returns `true`
> when code is compiled for the 32–bit iOS simulator.

You can combine and negate compilation conditions using the logical operators
`&&`, `||`, and `!`
and use parentheses for grouping.
These operators have the same associativity and precedence as the
logical operators that are used to combine ordinary Boolean expressions.

Similar to an `if` statement,
you can add multiple conditional branches to test for different compilation conditions.
You can add any number of additional branches using `#elseif` clauses.
You can also add a final additional branch using an `#else` clause.
Conditional compilation blocks that contain multiple branches
have the following form:

```swift
#if <#compilation condition 1#>
    <#statements to compile if compilation condition 1 is true#>
#elseif <#compilation condition 2#>
    <#statements to compile if compilation condition 2 is true#>
#else
    <#statements to compile if both compilation conditions are false#>
#endif
```

> Note: Each statement in the body of a conditional compilation block is parsed
> even if it's not compiled.
> However, there's an exception
> if the compilation condition includes a `swift()` or `compiler()` platform condition:
> The statements are parsed
> only if the language or compiler version matches
> what is specified in the platform condition.
> This exception ensures that an older compiler doesn't attempt to parse
> syntax introduced in a newer version of Swift.

For information about how you can wrap
explicit member expressions in conditional compilation blocks,
see [Explicit Member Expression](Expressions.md#Explicit-Member-Expression).

> Grammar of a conditional compilation block:
>
> *conditional-compilation-block* → *if-directive-clause* *elseif-directive-clauses*_?_ *else-directive-clause*_?_ *endif-directive*
>
> *if-directive-clause* → *if-directive* *compilation-condition* *statements*_?_ \
> *elseif-directive-clauses* → *elseif-directive-clause* *elseif-directive-clauses*_?_ \
> *elseif-directive-clause* → *elseif-directive* *compilation-condition* *statements*_?_ \
> *else-directive-clause* → *else-directive* *statements*_?_ \
> *if-directive* → **`#if`** \
> *elseif-directive* → **`#elseif`** \
> *else-directive* → **`#else`** \
> *endif-directive* → **`#endif`**
>
> *compilation-condition* → *platform-condition* \
> *compilation-condition* → *identifier* \
> *compilation-condition* → *boolean-literal* \
> *compilation-condition* → **`(`** *compilation-condition* **`)`** \
> *compilation-condition* → **`!`** *compilation-condition* \
> *compilation-condition* → *compilation-condition* **`&&`** *compilation-condition* \
> *compilation-condition* → *compilation-condition* **`||`** *compilation-condition*
>
> *platform-condition* → **`os`** **`(`** *operating-system* **`)`** \
> *platform-condition* → **`arch`** **`(`** *architecture* **`)`** \
> *platform-condition* → **`swift`** **`(`** **`>=`** *swift-version* **`)`** | **`swift`** **`(`** **`<`** *swift-version* **`)`** \
> *platform-condition* → **`compiler`** **`(`** **`>=`** *swift-version* **`)`** | **`compiler`** **`(`** **`<`** *swift-version* **`)`** \
> *platform-condition* → **`canImport`** **`(`** *import-path* **`)`** \
> *platform-condition* → **`targetEnvironment`** **`(`** *environment* **`)`**
>
> *operating-system* → **`macOS`** | **`iOS`** | **`watchOS`** | **`tvOS`** | **`visionOS`** | **`Linux`** | **`Windows`** \
> *architecture* → **`arm`** | **`arm64`** | **`i386`** | **`wasm32`** | **`x86_64`** \
> *swift-version* → *decimal-digits* *swift-version-continuation*_?_ \
> *swift-version-continuation* → **`.`** *decimal-digits* *swift-version-continuation*_?_ \
> *environment* → **`simulator`** | **`macCatalyst`**

<!--
  Testing notes:

  !!true doesn't work but !(!true) does -- this matches normal expressions
  #if can be nested, as expected

  Also, the body of a conditional compilation block contains *zero* or more statements.
  Thus, this is allowed:
      #if
      #elseif
      #else
      #endif
-->

### Line Control Statement

A line control statement is used to specify a line number and filename
that can be different from the line number and filename of the source code being compiled.
Use a line control statement to change the source code location
used by Swift for diagnostic and debugging purposes.

A line control statement has the following forms:

```swift
#sourceLocation(file: <#file path#>, line: <#line number#>)
#sourceLocation()
```

The first form of a line control statement changes the values
of the `#line`, `#file`, `#fileID`, and `#filePath`
literal expressions, beginning with the line of code following the line control statement.
The *line number* changes the value of `#line`,
and is any integer literal greater than zero.
The *file path* changes the value of `#file`, `#fileID`, and `#filePath`,
and is a string literal.
The specified string becomes the value of `#filePath`,
and the last path component of the string is used by the value of `#fileID`.
For information about `#file`, `#fileID`, and `#filePath`,
see [Literal Expression](Expressions.md#Literal-Expression).

The second form of a line control statement, `#sourceLocation()`,
resets the source code location back to the default line numbering and file path.

> Grammar of a line control statement:
>
> *line-control-statement* → **`#sourceLocation`** **`(`** **`file:`** *file-path* **`,`** **`line:`** *line-number* **`)`** \
> *line-control-statement* → **`#sourceLocation`** **`(`** **`)`** \
> *line-number* → A decimal integer greater than zero \
> *file-path* → *static-string-literal*

### Compile-Time Diagnostic Statement

Prior to Swift 5.9,
the `#warning` and `#error` statements emit a diagnostic during compilation.
This behavior is now provided by
the [`warning(_:)`][] and [`error(_:)`][] macros in the Swift standard library.

[`warning(_:)`]: https://developer.apple.com/documentation/swift/warning(_:)
[`error(_:)`]: https://developer.apple.com/documentation/swift/error(_:)

## Availability Condition

An *availability condition* is used as a condition of an `if`, `while`,
and `guard` statement to query the availability of APIs at runtime,
based on specified platforms arguments.

An availability condition has the following form:

```swift
if #available(<#platform name#> <#version#>, <#...#>, *) {
    <#statements to execute if the APIs are available#>
} else {
    <#fallback statements to execute if the APIs are unavailable#>
}
```

You use an availability condition to execute a block of code,
depending on whether the APIs you want to use are available at runtime.
The compiler uses the information from the availability condition
when it verifies that the APIs in that block of code are available.

The availability condition takes a comma-separated list of platform names and versions.
Use `iOS`, `macOS`, `watchOS`, `tvOS` and `visionOS` for the platform names,
and include the corresponding version numbers.
The `*` argument is required and specifies that, on any other platform,
the body of the code block guarded by the availability condition
executes on the minimum deployment target specified by your target.

Unlike Boolean conditions, you can't combine availability conditions using
logical operators like `&&` and `||`.
Instead of using `!` to negate an availability condition,
use an unavailability condition, which has the following form:

```swift
if #unavailable(<#platform name#> <#version#>, <#...#>) {
    <#fallback statements to execute if the APIs are unavailable#>
} else {
    <#statements to execute if the APIs are available#>
}
```

The `#unavailable` form is syntactic sugar that negates the condition.
In an unavailability condition,
the `*` argument is implicit and must not be included.
It has the same meaning as the `*` argument in an availability condition.

> Grammar of an availability condition:
>
> *availability-condition* → **`#available`** **`(`** *availability-arguments* **`)`** \
> *availability-condition* → **`#unavailable`** **`(`** *availability-arguments* **`)`** \
> *availability-arguments* → *availability-argument* | *availability-argument* **`,`** *availability-arguments* \
> *availability-argument* → *platform-name* *platform-version* \
> *availability-argument* → **`*`**
>
>
>
> *platform-name* → **`iOS`** | **`iOSApplicationExtension`** \
> *platform-name* → **`macOS`** | **`macOSApplicationExtension`** \
> *platform-name* → **`macCatalyst`** | **`macCatalystApplicationExtension`** \
> *platform-name* → **`watchOS`** | **`watchOSApplicationExtension`** \
> *platform-name* → **`tvOS`** | **`tvOSApplicationExtension`** \
> *platform-name* → **`visionOS`** | **`visionOSApplicationExtension`** \
> *platform-version* → *decimal-digits* \
> *platform-version* → *decimal-digits* **`.`** *decimal-digits* \
> *platform-version* → *decimal-digits* **`.`** *decimal-digits* **`.`** *decimal-digits*

<!--
  If you need to add a new platform to this list,
  you probably need to update the list under @available too.
-->

<!--
This source file is part of the Swift.org open source project

Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-->
