Skip to content

Commit 7e76588

Browse files
committed
Expand outline of the new section in the guide
1 parent efefc23 commit 7e76588

File tree

1 file changed

+36
-25
lines changed

1 file changed

+36
-25
lines changed

TSPL.docc/LanguageGuide/ErrorHandling.md

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -708,42 +708,53 @@ XXX OUTLINE XXX
708708
However, you can write `throws(SomeErrorType)`
709709
to throw errors of a specific concrete type.
710710

711-
- What is a boxed protocol (aka existential) error type?
712-
713-
- What is a concrete error type?
714-
715711
- Because you write a type after `throws`
716712
this syntax is also called "typed throws".
717713

714+
- A boxed protocol (aka existential) type matches the reality of most code.
715+
At compile time, you don't know every possible way things could go wrong.
716+
In particular, some errors will come from calling other throwing functions.
717+
718+
- In contrast, a concrete error type is useful:
719+
720+
* When the code that throws errors
721+
and the code that handles those errors
722+
are all part of the same larger unit,
723+
like a package or module or library.
724+
These errors are an implementation detail
725+
that users of the library don't see or recover from.
726+
727+
* In code that only rethrows errors,
728+
especially when the throwing code comes from a closure the caller provided.
729+
Example: `map` in the stdlib.
730+
Xref to reference section -- this chapter doesn't discuss rethrows
731+
732+
* In an environment where runtime memory allocation isn't possible,
733+
like a constrained embedded system.
734+
Throwing an instance of `any Error` requires allocation.
735+
The type isn't known at compile time -- allocation happens at run time.
736+
(Aside: The performance cost of allocation is small.)
737+
738+
* In code that has no dependencies, and only ever throws its own errors.
739+
TR: Does this include not depending on the stdlib?
740+
718741
- You can also use opaque types like `throws(some MyErrorProtocol)` --
719742
this is still "concrete" in sense that
720743
the errors are all instances of the concrete type
721744
that's hidden behind the opaque type.
722745

723-
- When should I use concrete error types?
724-
(See SE-0413 for a list.)
725-
Why shouldn't I just use this everywhere?
726-
727-
- How do I write a concrete error type for a `do` block?
728-
729-
- How do I write a concrete error type for a throwing function?
730-
731-
- What's the type-system relationship
732-
between plain `throws` and `throws(SomeErrorType)`?
733-
When can I interchange them?
746+
- To specify the error type for a `do` block or a throwing function,
747+
write `throws(E)` where `E` is an error type.
748+
For example -- insert `summarize` from RUNNING EXAMPLE below.
734749

735750
- If a function or `do` block throws only errors of a single type,
736751
the compiler infers that as the concrete error type.
737-
You can explicitly write `throws(any Error` to suppress that.
752+
You can explicitly write `throws(any Error)` to suppress that.
738753

739-
- How do I exhaustively handle errors of a concrete type in a `catch` block?
740-
741-
<!--
742-
The outline above doesn't discuss
743-
the similarity and comparison between throws(E) and rethrows
744-
because this chapter doesn't discuss rethrows.
745-
That information will go in the reference.
746-
-->
754+
- For a normal error (of boxed protocol type)
755+
the `catch` clause needs to either include a general catch/default
756+
or to propagate the errors it doesn't handle.
757+
For a typed error, the catch clause can be exhaustive.
747758

748759
XXX RUNNING EXAMPLE XXX
749760

@@ -770,7 +781,7 @@ func summarize(_ ratings: [Int]) throws(StatisticsError) {
770781
}
771782

772783
func printSummary(_ ratings: [Int]) {
773-
do {
784+
do throws(StatisticsError) {
774785
try summarize(ratings)
775786
} catch {
776787
switch error {

0 commit comments

Comments
 (0)