Skip to content

Commit d5ec87e

Browse files
authored
Merge pull request #960 from msehnout/master
Add section about diverging functions
2 parents 5488e80 + a1737ff commit d5ec87e

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
- [Iterator::any](fn/closures/closure_examples/iter_any.md)
7171
- [Iterator::find](fn/closures/closure_examples/iter_find.md)
7272
- [Higher Order Functions](fn/hof.md)
73+
- [Diverging functions](fn/diverging.md)
7374

7475
- [Modules](mod.md)
7576
- [Visibility](mod/visibility.md)

src/fn/diverging.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Diverging functions
2+
3+
Diverging functions never return. They are marked using `!`, which is an empty type.
4+
5+
```rust
6+
fn foo() -> ! {
7+
panic!("This call never returns.");
8+
}
9+
```
10+
11+
As opposed to all the other types, this one cannot be instantiated, because the
12+
set of all possible values this type can have is empty. Note, that it is
13+
different from the `()` type, which has exactly one possible value.
14+
15+
For example, this functions returns as usual, although there is no information
16+
in the return value.
17+
18+
```rust
19+
fn some_fn() {
20+
()
21+
}
22+
23+
fn main() {
24+
let a: () = some_fn();
25+
println!("This functions returns and you can see this line.")
26+
}
27+
```
28+
29+
As opposed to this function, which will never return the control back to the caller.
30+
31+
```rust,ignore
32+
#![feature(never_type)]
33+
34+
fn main() {
35+
let x: ! = panic!("This call never returns.");
36+
println!("You will never see this line!");
37+
}
38+
```
39+
40+
Although this might seem like an abstract concept, it is in fact very useful and
41+
often handy. The main advantage of this type is that it can be cast to any other
42+
one and therefore used at places where an exact type is required, for instance
43+
in `match` branches. This allows us to write code like this:
44+
45+
```rust
46+
fn main() {
47+
fn sum_odd_numbers(up_to: u32) -> u32 {
48+
let mut acc = 0;
49+
for i in 0..up_to {
50+
// Notice that the return type of this match expression must be u32
51+
// because of the type of the "addition" variable.
52+
let addition: u32 = match i%2 == 1 {
53+
// The "i" variable is of type u32, which is perfectly fine.
54+
true => i,
55+
// On the other hand, the "continue" expression does not return
56+
// u32, but it is still fine, because it never returns and therefore
57+
// does not violate the type requirements of the match expression.
58+
false => continue,
59+
};
60+
acc += addition;
61+
}
62+
acc
63+
}
64+
println!("Sum of odd numbers up to 9 (excluding): {}", sum_odd_numbers(9));
65+
}
66+
```
67+
68+
It is also the return type of functions that loop forever (e.g. `loop {}`) like
69+
network servers or functions that terminates the process (e.g. `exit()`).

0 commit comments

Comments
 (0)