keyword. For example, we can create the alias `Kilometers` to `i32` like so:
```rust
-type Kilometers = i32;
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs:here}}
```
Now, the alias `Kilometers` is a *synonym* for `i32`; unlike the `Millimeters`
values of type `i32`:
```rust
-type Kilometers = i32;
-
-let x: i32 = 5;
-let y: Kilometers = 5;
-
-println!("x + y = {}", x + y);
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-04-kilometers-alias/src/main.rs:there}}
```
Because `Kilometers` and `i32` are the same type, we can add values of both
code like that in Listing 19-24.
```rust
-let f: Box<dyn Fn() + Send + 'static> = Box::new(|| println!("hi"));
-
-fn takes_long_type(f: Box<dyn Fn() + Send + 'static>) {
- // --snip--
-}
-
-fn returns_long_type() -> Box<dyn Fn() + Send + 'static> {
- // --snip--
-# Box::new(|| ())
-}
+{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-24/src/main.rs:here}}
```
<span class="caption">Listing 19-24: Using a long type in many places</span>
can replace all uses of the type with the shorter alias `Thunk`.
```rust
-type Thunk = Box<dyn Fn() + Send + 'static>;
-
-let f: Thunk = Box::new(|| println!("hi"));
-
-fn takes_long_type(f: Thunk) {
- // --snip--
-}
-
-fn returns_long_type() -> Thunk {
- // --snip--
-# Box::new(|| ())
-}
+{{#rustdoc_include ../listings/ch19-advanced-features/listing-19-25/src/main.rs:here}}
```
<span class="caption">Listing 19-25: Introducing a type alias `Thunk` to reduce
the `Write` trait:
```rust
-use std::io::Error;
-use std::fmt;
-
-pub trait Write {
- fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
- fn flush(&mut self) -> Result<(), Error>;
-
- fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>;
- fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Error>;
-}
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-05-write-trait/src/lib.rs}}
```
The `Result<..., Error>` is repeated a lot. As such, `std::io` has this type of
alias declaration:
```rust
-type Result<T> = std::result::Result<T, std::io::Error>;
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs:here}}
```
Because this declaration is in the `std::io` module, we can use the fully
filled in as `std::io::Error`. The `Write` trait function signatures end up
looking like this:
-```rust,ignore
-pub trait Write {
- fn write(&mut self, buf: &[u8]) -> Result<usize>;
- fn flush(&mut self) -> Result<()>;
-
- fn write_all(&mut self, buf: &[u8]) -> Result<()>;
- fn write_fmt(&mut self, fmt: Arguments) -> Result<()>;
-}
+```rust
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-06-result-alias/src/lib.rs:there}}
```
The type alias helps in two ways: it makes code easier to write *and* it gives
because it stands in the place of the return type when a function will never
return. Here is an example:
-```rust,ignore
-fn bar() -> ! {
- // --snip--
-}
+```rust
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-07-never-type/src/lib.rs:here}}
```
This code is read as “the function `bar` returns never.” Functions that return
But what use is a type you can never create values for? Recall the code from
Listing 2-5; we’ve reproduced part of it here in Listing 19-26.
-```rust
-# let guess = "3";
-# loop {
-let guess: u32 = match guess.trim().parse() {
- Ok(num) => num,
- Err(_) => continue,
-};
-# break;
-# }
+```rust,ignore
+{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs:ch19}}
```
<span class="caption">Listing 19-26: A `match` with an arm that ends in
for example, the following code doesn’t work:
```rust,ignore,does_not_compile
-let guess = match guess.trim().parse() {
- Ok(_) => 5,
- Err(_) => "hello",
-}
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-08-match-arms-different-types/src/main.rs:here}}
```
The type of `guess` in this code would have to be an integer *and* a string,
is its definition:
```rust,ignore
-impl<T> Option<T> {
- pub fn unwrap(self) -> T {
- match self {
- Some(val) => val,
- None => panic!("called `Option::unwrap()` on a `None` value"),
- }
- }
-}
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-09-unwrap-definition/src/lib.rs:here}}
```
In this code, the same thing happens as in the `match` in Listing 19-26: Rust
One final expression that has the type `!` is a `loop`:
```rust,ignore
-print!("forever ");
-
-loop {
- print!("and ever ");
-}
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-10-loop-returns-never/src/main.rs:here}}
```
Here, the loop never ends, so `!` is the value of the expression. However, this
`str`. Consider the following code, which does not work:
```rust,ignore,does_not_compile
-let s1: str = "Hello there!";
-let s2: str = "How's it going?";
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-11-cant-create-str/src/main.rs:here}}
```
Rust needs to know how much memory to allocate for any value of a particular
That is, a generic function definition like this:
```rust,ignore
-fn generic<T>(t: T) {
- // --snip--
-}
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-12-generic-fn-definition/src/lib.rs}}
```
is actually treated as though we had written this:
```rust,ignore
-fn generic<T: Sized>(t: T) {
- // --snip--
-}
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/src/lib.rs}}
```
By default, generic functions will work only on types that have a known size at
restriction:
```rust,ignore
-fn generic<T: ?Sized>(t: &T) {
- // --snip--
-}
+{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs}}
```
A trait bound on `?Sized` is the opposite of a trait bound on `Sized`: we would