@@ -717,58 +717,33 @@ The error handling code in the examples above
717
717
always includes a default case to handle errors
718
718
that don't have their own specific ` catch ` clause.
719
719
720
- In some special cases,
721
- you might write code that's specific about what error it throws:
720
+ Most Swift code doesn't specify the type for the errors it throws.
721
+ However,
722
+ in some special cases,
723
+ you might limit code to throwing errors of only one specific type:
722
724
723
725
- When running code on an embedded system
724
- where dynamic allocation of memory isn't possible .
726
+ that doesn't support dynamic allocation of memory.
725
727
Throwing an instance ` any Error ` or another boxed protocol type
726
- requires allocating memory at run time to store the error.
727
- Throwing an error of a specific type instead
728
- lets Swift allocate that memory upfront.
728
+ requires allocating memory at runtime to store the error.
729
+ Throwing an error of a specific type
730
+ lets Swift allocate that memory upfront instead .
729
731
730
- - When the errors are an implementation detail of a library ,
731
- or some other unit of code ,
732
+ - When the errors are used only within some unit of code ,
733
+ like a library ,
732
734
and aren't part of the interface to that code.
733
- Because only the library's code throws errors ---
734
- it doesn't propagate errors from other code ---
735
+ Because the errors come only from the library,
736
+ and not from other dependencies or the library's clients,
735
737
you can make an exhaustive list of all possible failures.
736
- And because the library always handles its own errors,
737
-
738
-
739
- Because all of these errors are thrown within the library's code,
738
+ And because these errors are an implementation detail of the library,
740
739
and they're always handled within that library.
741
- Because
742
- Because the library's clients never see the errors,
743
- ◊ the API surface expressively limitations don't matter
744
-
745
- -
746
- * In code that only rethrows errors,
747
- especially when the throwing code comes from a closure the caller provided.
748
- (However, neither rethrows nor typed throws is a strict superset of the other.)
749
- Example: ` map ` in the stdlib.
750
- Xref to reference section -- this chapter doesn't discuss rethrows
751
740
752
-
753
- In most code,
754
- you don't specify the type for the errors it throws,
755
- implicitly throwing an error of type ` any Error `
756
- However,
757
- Swift also supports
758
- some code only throws errors of a specific type.
759
- in some places your code only throws
760
- you might need to write code that throws errors of only a specific type,
761
- so it's useful to specify that type.
762
-
763
- - When you throw errors from code that
764
- doesn't depend on any other throwing code,
765
- and throws only its own errors.
766
- <!-- XXX This also feels like "implementation detail errors" -->
767
- <!-- XXX TR: Does this include not depending on the stdlib? -->
768
-
769
- - When you rethrow errors,
770
- if you want to preserve the error type.
771
- <!-- XXX TR: Need to motivate why you'd use rethrow vs throws(T) -->
741
+ - In code that only throws errors that were thrown elsewhere,
742
+ like a function that takes a closure argument
743
+ and propagates any errors from that closure.
744
+ For a comparison between ` rethrows `
745
+ and throwing a specific, generic, error type
746
+ see < doc:Declarations:Rethrowing-Functions-and-Methods > .
772
747
773
748
For example,
774
749
consider code that summarizes ratings
@@ -781,7 +756,7 @@ enum StatisticsError: Error {
781
756
}
782
757
```
783
758
784
- To specify that a function throws only ` StatisticsError `
759
+ To specify that a function throws only ` StatisticsError ` values as its errors
785
760
you write ` throws(StatisticsError) ` when declaring the function,
786
761
instead of just writing ` throws ` .
787
762
This syntax is also called * typed throws*
@@ -805,44 +780,54 @@ In the code above,
805
780
the ` summarize(_:) ` function summarizes a list of ratings
806
781
expressed on a scale of 1 to 3.
807
782
This function throws an instance of ` StatisticsError ` if the input isn't valid.
808
-
809
- You can use the shorthand notation ` throw .noRatings `
810
- instead of writing ` throw StatisticsError.noRatings `
783
+ Both places in the code above that throw an error
784
+ omit the type of the error
811
785
because the function's error type is already defined.
786
+ You can use the short form like ` throw .noRatings `
787
+ instead of writing ` throw StatisticsError.noRatings `
788
+ when throwing an error in a function like this.
812
789
813
-
814
- ◊ throws(StatisticsError) is a subtype of throws(any Error)
815
- ◊ so you can write ` try summarize(...) ` in a plain ` throwing ` context too
816
- - Most code that throws errors just writes ` throws ` .
817
- This is the same as writing ` throws(any Error) ` .
818
- However, you can write ` throws(SomeErrorType) `
819
- to throw errors of a specific concrete type.
820
-
821
-
822
-
823
- When you write a specific error type,
790
+ When you write a specific error type at the start of the function,
824
791
Swift checks that you don't throw any other errors.
825
792
For example,
826
793
if you tried to use ` VendingMachineError ` from examples earlier in this chapter
827
794
in the ` summarize(_:) ` function above,
828
795
that code would produce an error at compile time.
829
796
830
- ◊ rewrite
831
- Code that throws a single specific error type
832
- doesn't need to include the default ` catch ` clause ---
833
- instead, Swift verifies that every possible error value
834
- has a corresponding ` catch ` clause.
797
+ You can call a function that uses typed throws
798
+ from within a regular throwing function:
835
799
800
+ ``` swift
801
+ func someThrowingFunction () -> throws {
802
+ let ratings = [1 , 2 , 3 , 2 , 2 , 1 ]
803
+ try summarize (ratings)
804
+ }
805
+ ```
806
+
807
+ The code above doesn't specify an error type for ` someThrowingFunction() ` ,
808
+ so it throws ` any Error ` .
809
+ You could also write the error type explicitly as ` throws(any Error) ` ---
810
+ the code below is equivalent to the code above:
836
811
812
+ ``` swift
813
+ func someThrowingFunction () -> throws (any Error ) {
814
+ let ratings = [1 , 2 , 3 , 2 , 2 , 1 ]
815
+ try summarize (ratings)
816
+ }
817
+ ```
837
818
819
+ In this code,
820
+ ` someThrowingFunction() ` propagates any errors that ` summarize(_:) ` throws.
821
+ The errors from ` summarize(_:) ` are always ` StatisticsError ` values,
822
+ which is also a valid error for ` someThrowingFunction() ` to throw.
823
+ <!-- XXX Expand on subtyping here? -->
838
824
839
- In addition to specifying the error type for a function,
840
- you can also write a specific error type
841
- in a ` do ` -` catch ` block.
825
+ In addition to specifying a function's error type,
826
+ you can also write a specific error type for a ` do ` -` catch ` statement.
842
827
For example:
843
828
844
829
``` swift
845
- let ratings = [1 , 2 , 3 , 2 , 2 , 1 ]
830
+ let ratings = []
846
831
do throws (StatisticsError) {
847
832
try summarize (ratings)
848
833
} catch {
@@ -853,33 +838,60 @@ do throws(StatisticsError) {
853
838
print (" Invalid rating: \( rating ) " )
854
839
}
855
840
}
856
- // Prints XXX
841
+ // Prints "No ratings available"
857
842
```
858
843
859
- In this code, XXX
860
-
844
+ In this code,
845
+ writing ` do throws(StatisticsError) ` indicates that
846
+ the ` do ` -` catch ` statement throws ` StatisticsError ` values as its errors.
847
+ Like other ` do ` -` catch ` statements,
848
+ the ` catch ` clause can either handle every possible error,
849
+ or it can propagate unhandled errors for some surrounding scope to handle.
850
+ Here, it handles all of the errors,
851
+ using a switch with one case for each enumeration value.
852
+ Like other ` catch ` clauses that don't have a pattern,
853
+ the clause matches any error
854
+ and binds the error to a local constant named ` error ` .
855
+ Because the ` do ` -` catch ` statement throws ` StatisticsError ` values,
856
+ ` error ` is a value of type ` StatisticsError ` .
861
857
862
- XXX
863
- If a function or ` do ` block throws only errors of a single type,
864
- the compiler infers that as the concrete error type.
865
- You can explicitly write ` throws(any Error) ` to suppress that.
858
+ <!-- XXX show multiple catch clauses with different patterns? -->
866
859
860
+ The ` catch ` clause above uses a switch
861
+ to match and handle each possible error.
862
+ If you tried to add a new case to ` StatisticsError `
863
+ without updating the error-handling code,
864
+ Swift would give you an error
865
+ because the switch wouldn't be exhaustive anymore.
866
+ For a library that catches all of its own errors,
867
+ you could use this approach to ensure any new errors
868
+ get corresponding new code to handle them.
867
869
868
- ## XXX OUTLINE XXX
870
+ If a function or ` do ` block throws only errors of a single type,
871
+ Swift infers that this code is using typed throws.
872
+ Using this shorter syntax,
873
+ you could write the ` do ` -` catch ` example above as follows:
869
874
870
- - You can also use opaque types like ` throws(some MyErrorProtocol) ` --
871
- this is still "concrete" in sense that
872
- the errors are all instances of the concrete type
873
- that's hidden behind the opaque type.
874
- And there's still one specific error type.
875
+ ``` swift
876
+ let ratings = []
877
+ do {
878
+ try summarize (ratings)
879
+ } catch {
880
+ switch error {
881
+ case .noRatings :
882
+ print (" No ratings available" )
883
+ case .invalidRating (let rating):
884
+ print (" Invalid rating: \( rating ) " )
885
+ }
886
+ }
887
+ // Prints "No ratings available"
888
+ ```
875
889
876
- - For a normal error (of boxed protocol type)
877
- the ` catch ` clause needs to either include a general catch/default
878
- that handles errors whose types the other clauses don't handle,
879
- or to propagate the errors it doesn't handle.
880
- For a typed error, the catch clause can be exhaustive
881
- without a default clause
882
- by handling just that specific error type.
890
+ Even though the ` do ` -` catch ` block above
891
+ doesn't specify what type of error it throws,
892
+ it's still understood as throwing ` StatisticsError ` .
893
+ You can explicitly write ` throws(any Error) `
894
+ to avoid letting Swift infer typed throws.
883
895
884
896
## Specifying Cleanup Actions
885
897
0 commit comments