Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b60c3e2
Closes #15919
bombless Apr 30, 2015
4c8b813
Closes #15919
bombless Apr 30, 2015
9b3d315
std: Update crate docs
brson May 8, 2015
4b52059
Add error explanations for E0049, E0050, E0069, E0106, E0107, E0166.
May 11, 2015
4fee8d3
Add error explanation for E0066.
May 12, 2015
c3dc769
Add error explanation for E0322.
May 12, 2015
71f6ed8
Remove comment description of E0234.
May 12, 2015
cbeda68
Add error explanation for E0201.
May 12, 2015
46753da
Record correct span for static mut items
GSam May 12, 2015
a22b327
book: typo fixes, wording improvements.
wheals May 12, 2015
6f3701d
readme: Rework the arch support matrix
richo May 12, 2015
6ebba71
doc: Address feedback
brson May 12, 2015
33a30f2
Improve error explanations for E0049, E0050, E0166.
May 12, 2015
5c77f0d
Remove extended explanation of lifetime elision from E0106.
May 12, 2015
0ad15bb
TRPL: release channels
steveklabnik May 7, 2015
9a3e98b
TRPL: Drop
steveklabnik May 11, 2015
fc6372e
TRPL: Rust inside other languages
steveklabnik May 12, 2015
2ba6169
TRPL: dining philosophers
steveklabnik May 11, 2015
457aed7
trpl: move tuple-structs.md into structs.md
geofft May 12, 2015
797d8e2
trpl/structs: Document unit-like structs
geofft May 12, 2015
8d50216
trpl/enums: Rewrite
geofft May 12, 2015
f59f41e
trpl/match: Add an example for matching on enums
geofft May 13, 2015
d3dd694
Rollup merge of #24987 - bombless:large-array, r=pnkfelix
steveklabnik May 13, 2015
6834d37
Rollup merge of #25224 - brson:stddoc, r=steveklabnik
steveklabnik May 13, 2015
273224b
Rollup merge of #25317 - steveklabnik:trpl_drop, r=alexcrichton
steveklabnik May 13, 2015
8f16862
Rollup merge of #25321 - steveklabnik:second_tutorial, r=alexcrichton
steveklabnik May 13, 2015
b833737
Rollup merge of #25324 - richo:richo-compat, r=huonw
steveklabnik May 13, 2015
cd1f94a
Rollup merge of #25328 - nham:E0106_E0107, r=alexcrichton
steveklabnik May 13, 2015
2b1a1ef
Rollup merge of #25333 - GSam:master, r=nrc
steveklabnik May 13, 2015
b53392c
Merge branch 'doc_release_channels' into rollup
steveklabnik May 13, 2015
80381c3
Merge branch 'doc-fixes' of https://github.com/wheals/rust into rollup
steveklabnik May 13, 2015
2c01eac
Merge branch 'trpl_embedding' into rollup
steveklabnik May 13, 2015
758d568
Merge branch 'trpl-fix-enums' of https://github.com/geofft/rust into …
steveklabnik May 13, 2015
1d34f92
Update error messages for tests in compile-fail for E0066 and E0069.
May 13, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/doc/trpl/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
* [References and Borrowing](references-and-borrowing.md)
* [Lifetimes](lifetimes.md)
* [Mutability](mutability.md)
* [Structs](structs.md)
* [Enums](enums.md)
* [Match](match.md)
* [Structs](structs.md)
* [Patterns](patterns.md)
* [Method Syntax](method-syntax.md)
* [Vectors](vectors.md)
Expand All @@ -47,7 +47,6 @@
* [Universal Function Call Syntax](ufcs.md)
* [Crates and Modules](crates-and-modules.md)
* [`const` and `static`](const-and-static.md)
* [Tuple Structs](tuple-structs.md)
* [Attributes](attributes.md)
* [`type` aliases](type-aliases.md)
* [Casting between types](casting-between-types.md)
Expand Down
96 changes: 45 additions & 51 deletions src/doc/trpl/enums.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,63 @@
% Enums

Rust has a ‘sum type’, an `enum`. Enums are an incredibly useful feature of
Rust, and are used throughout the standard library. An `enum` is a type which
relates a set of alternates to a specific name. For example, below we define
`Character` to be either a `Digit` or something else.
An `enum` in Rust is a type that represents data that could be one of
several possible variants:

```rust
enum Character {
Digit(i32),
Other,
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
```

Most types are allowed as the variant components of an `enum`. Here are some
examples:
Each variant can optionally have data associated with it. The syntax for
defining variants resembles the syntaxes used to define structs: you can
have variants with no data (like unit-like structs), variants with named
data, and variants with unnamed data (like tuple structs). Unlike
separate struct definitions, however, an `enum` is a single type. A
value of the enum can match any of the variants. For this reason, an
enum is sometimes called a ‘sum type’: the set of possible values of the
enum is the sum of the sets of possible values for each variant.

```rust
struct Empty;
struct Color(i32, i32, i32);
struct Length(i32);
struct Stats { Health: i32, Mana: i32, Attack: i32, Defense: i32 }
struct HeightDatabase(Vec<i32>);
```

You see that, depending on its type, an `enum` variant may or may not hold data.
In `Character`, for instance, `Digit` gives a meaningful name for an `i32`
value, where `Other` is only a name. However, the fact that they represent
distinct categories of `Character` is a very useful property.

The variants of an `enum` by default are not comparable with equality operators
(`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not support other
binary operations such as `*` and `+`. As such, the following code is invalid
for the example `Character` type:

```rust,ignore
// These assignments both succeed
let ten = Character::Digit(10);
let four = Character::Digit(4);

// Error: `*` is not implemented for type `Character`
let forty = ten * four;
We use the `::` syntax to use the name of each variant: they’re scoped by the name
of the `enum` itself. This allows both of these to work:

// Error: `<=` is not implemented for type `Character`
let four_is_smaller = four <= ten;
```rust
# enum Message {
# Move { x: i32, y: i32 },
# }
let x: Message = Message::Move { x: 3, y: 4 };

enum BoardGameTurn {
Move { squares: i32 },
Pass,
}

// Error: `==` is not implemented for type `Character`
let four_equals_ten = four == ten;
let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 };
```

We use the `::` syntax to use the name of each variant: They’re scoped by the name
of the `enum` itself. This allows both of these to work:
Both variants are named `Move`, but since they’re scoped to the name of
the enum, they can both be used without conflict.

A value of an enum type contains information about which variant it is,
in addition to any data associated with that variant. This is sometimes
referred to as a ‘tagged union’, since the data includes a ‘tag’
indicating what type it is. The compiler uses this information to
enforce that you’re accessing the data in the enum safely. For instance,
you can’t simply try to destructure a value as if it were one of the
possible variants:

```rust,ignore
Character::Digit(10);
Hand::Digit;
fn process_color_change(msg: Message) {
let Message::ChangeColor(r, g, b) = msg; // compile-time error
}
```

Both variants are named `Digit`, but since they’re scoped to the `enum` name
there's no ambiguity.

Not supporting these operations may seem rather limiting, but it’s a limitation
which we can overcome. There are two ways: by implementing equality ourselves,
or by pattern matching variants with [`match`][match] expressions, which you’ll
learn in the next section. We don’t know enough about Rust to implement
equality yet, but we’ll find out in the [`traits`][traits] section.
We’ll see how to safely get data out of enums when we learn about the
[`match`][match] and [`if let`][if-let] statements in the next few
chapters.

[match]: match.html
[traits]: traits.html
[if-let]: if-let.html
37 changes: 37 additions & 0 deletions src/doc/trpl/match.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,40 @@ let number = match x {
```

Sometimes it’s a nice way of converting something from one type to another.

# Matching on enums

Another important use of the `match` keyword is to process the possible
variants of an enum:

```rust
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}

fn quit() { /* ... */ }
fn change_color(r: i32, g: i32, b: i32) { /* ... */ }
fn move_cursor(x: i32, y: i32) { /* ... */ }

fn process_message(msg: Message) {
match msg {
Message::Quit => quit(),
Message::ChangeColor(r, g, b) => change_color(r, g, b),
Message::Move { x: x, y: y } => move_cursor(x, y),
Message::Write(s) => println!("{}", s),
};
}
```

Again, the Rust compiler checks exhaustiveness, so it demands that you
have a match arm for every variant of the enum. If you leave one off, it
will give you a compile-time error unless you use `_`.

Unlike the previous uses of `match`, you can’t use the normal `if`
statement to do this. You can use the [`if let`][if-let] statement,
which can be seen as an abbreviated form of `match`.

[if-let][if-let.html]
79 changes: 79 additions & 0 deletions src/doc/trpl/structs.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,82 @@ ones, and it will copy the values you don’t specify:
let origin = Point3d { x: 0, y: 0, z: 0 };
let point = Point3d { z: 1, x: 2, .. origin };
```

# Tuple structs

Rust has another data type that’s like a hybrid between a [tuple][tuple] and a
struct, called a ‘tuple struct’. Tuple structs have a name, but
their fields don’t:

```rust
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
```

[tuple]: primitive-types.html#tuples

These two will not be equal, even if they have the same values:

```rust
# struct Color(i32, i32, i32);
# struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
```

It is almost always better to use a struct than a tuple struct. We would write
`Color` and `Point` like this instead:

```rust
struct Color {
red: i32,
blue: i32,
green: i32,
}

struct Point {
x: i32,
y: i32,
z: i32,
}
```

Now, we have actual names, rather than positions. Good names are important,
and with a struct, we have actual names.

There _is_ one case when a tuple struct is very useful, though, and that’s a
tuple struct with only one element. We call this the ‘newtype’ pattern, because
it allows you to create a new type, distinct from that of its contained value
and expressing its own semantic meaning:

```rust
struct Inches(i32);

let length = Inches(10);

let Inches(integer_length) = length;
println!("length is {} inches", integer_length);
```

As you can see here, you can extract the inner integer type through a
destructuring `let`, just as with regular tuples. In this case, the
`let Inches(integer_length)` assigns `10` to `integer_length`.

# Unit-like structs

You can define a struct with no members at all:

```rust
struct Electron;
```

Such a struct is called ‘unit-like’ because it resembles the empty
tuple, `()`, sometimes called ‘unit’. Like a tuple struct, it defines a
new type.

This is rarely useful on its own (although sometimes it can serve as a
marker type), but in combination with other features, it can become
useful. For instance, a library may ask you to create a structure that
implements a certain [trait][trait] to handle events. If you don’t have
any data you need to store in the structure, you can just create a
unit-like struct.
60 changes: 0 additions & 60 deletions src/doc/trpl/tuple-structs.md

This file was deleted.