@@ -1800,8 +1800,9 @@ the value has the corresponding @emph{function type}, and can be used
1800
1800
otherwise exactly as a function item (with a minor additional cost of calling
1801
1801
the function, as such a call is indirect). @xref {Ref.Type.Fn }.
1802
1802
1803
- Every control path in a function ends with either a @code {ret } or @code {be }
1804
- expression. If a control path lacks a @code {ret } expression in source code, an
1803
+ Every control path in a function ends with a @code {ret } or @code {be }
1804
+ expression or with a diverging expression (described later in this
1805
+ section). If a control path lacks a @code {ret } expression in source code, an
1805
1806
implicit @code {ret } expression is appended to the end of the control path
1806
1807
during compilation, returning the implicit @code {() } value.
1807
1808
@@ -1812,6 +1813,44 @@ fn add(int x, int y) -> int @{
1812
1813
@}
1813
1814
@end example
1814
1815
1816
+ A special kind of function can be declared with a @code {! } character where the
1817
+ output slot type would normally be. For example:
1818
+ @example
1819
+ fn my_err(str s) -> ! @{
1820
+ log s;
1821
+ fail;
1822
+ @}
1823
+ @end example
1824
+
1825
+ We call such functions ``diverging'' because they never return a value to the
1826
+ caller. Every control path in a diverging function must end with a @code {fail }
1827
+ or a call to another diverging function on every control path. The @code {! }
1828
+ annotation does @emph {not } denote a type. Rather, the result type
1829
+ of a diverging function is a special type called @math {\bot } (``bottom'') that
1830
+ unifies with any type. Rust has no syntax for @math {\bot }.
1831
+
1832
+ It might be necessary to declare a diverging function because as mentioned
1833
+ previously, the typechecker checks that every control path in a function ends
1834
+ with a @code {ret }, @code {be }, or diverging expression. So, if @code {my_err }
1835
+ were declared without the @code {! } annotation, the following code would not
1836
+ typecheck:
1837
+ @example
1838
+ fn f(int i) -> int @{
1839
+ if (i == 42) {
1840
+ ret 42;
1841
+ }
1842
+ else {
1843
+ my_err("Bad number!");
1844
+ }
1845
+ @}
1846
+ @end example
1847
+
1848
+ The typechecker would complain that @code {f } doesn't return a value in the
1849
+ @code {else } branch. Adding the @code {! } annotation on @code {my_err } would
1850
+ express that @code {f } requires no explicit @code {ret }, as if it returns
1851
+ control to the caller, it returns a value (true because it never returns
1852
+ control).
1853
+
1815
1854
@node Ref.Item.Pred
1816
1855
@subsection Ref.Item.Pred
1817
1856
@c * Ref.Item.Pred:: Items defining predicates.
0 commit comments