Skip to content

Commit 5ebf481

Browse files
committed
auto merge of #15956 : steveklabnik/rust/guide_crates, r=pcwalton
Also fixes a couple of filesystem references that I forgot to change. 😅
2 parents 87c78fd + 456c449 commit 5ebf481

File tree

1 file changed

+351
-9
lines changed

1 file changed

+351
-9
lines changed

src/doc/guide.md

+351-9
Original file line numberDiff line numberDiff line change
@@ -1770,7 +1770,7 @@ fn main() {
17701770

17711771
```{notrust,ignore}
17721772
$ cargo build
1773-
Compiling guessing_game v0.1.0 (file:/home/steve/tmp/guessing_game)
1773+
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
17741774
$
17751775
```
17761776

@@ -2042,7 +2042,7 @@ Let's try it out!
20422042

20432043
```{notrust,ignore}
20442044
$ cargo build
2045-
Compiling guessing_game v0.1.0 (file:/home/steve/tmp/guessing_game)
2045+
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
20462046
src/guessing_game.rs:22:15: 22:24 error: mismatched types: expected `uint` but found `core::option::Option<uint>` (expected uint but found enum core::option::Option)
20472047
src/guessing_game.rs:22 match cmp(input_num, secret_number) {
20482048
^~~~~~~~~
@@ -2246,7 +2246,7 @@ that `return`? If we give a non-number answer, we'll `return` and quit. Observe:
22462246
```{notrust,ignore}
22472247
$ cargo build
22482248
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
2249-
steve@computer:~/tmp/guessing_game$ ./target/guessing_game
2249+
$ ./target/guessing_game
22502250
Guess the number!
22512251
The secret number is: 59
22522252
Please input your guess.
@@ -2462,19 +2462,361 @@ rest of your Rust education.
24622462
Now that you're an expert at the basics, it's time to learn about some of
24632463
Rust's more unique features.
24642464

2465-
# iterators
2465+
# Crates and Modules
24662466

2467-
# Lambdas
2467+
Rust features a strong module system, but it works a bit differently than in
2468+
other programming languages. Rust's module system has two main components:
2469+
**crate**s, and **module**s.
2470+
2471+
A crate is Rust's unit of independent compilation. Rust always compiles one
2472+
crate at a time, producing either a library or an executable. However, executables
2473+
usually depend on libraries, and many libraries depend on other libraries as well.
2474+
To support this, crates can depend on other crates.
2475+
2476+
Each crate contains a hierarchy of modules. This tree starts off with a single
2477+
module, called the **crate root**. Within the crate root, we can declare other
2478+
modules, which can contain other modules, as deeply as you'd like.
2479+
2480+
Note that we haven't mentioned anything about files yet. Rust does not impose a
2481+
particular relationship between your filesystem structure and your module
2482+
structure. That said, there is a conventional approach to how Rust looks for
2483+
modules on the file system, but it's also overrideable.
2484+
2485+
Enough talk, let's build something! Let's make a new project called `modules`.
2486+
2487+
```{bash,ignore}
2488+
$ cd ~/projects
2489+
$ mkdir modules
2490+
$ cd modules
2491+
$ mkdir src
2492+
```
2493+
2494+
We need to make our two 'hello world' files. In `src/main.rs`:
2495+
2496+
```{rust}
2497+
fn main() {
2498+
println!("Hello, world!");
2499+
}
2500+
```
2501+
2502+
And in `Cargo.toml`:
2503+
2504+
```{notrust,ignore}
2505+
[package]
2506+
2507+
name = "modules"
2508+
version = "0.1.0"
2509+
authors = [ "someone@example.com" ]
2510+
```
2511+
2512+
Let's double check our work by compiling:
2513+
2514+
```{bash,ignore}
2515+
$ cargo build
2516+
Compiling modules v0.1.0 (file:/home/you/projects/modules)
2517+
$ ./target/modules
2518+
Hello, world!
2519+
```
2520+
2521+
Excellent! So, we already have a single crate here: our `src/main.rs` is a crate.
2522+
Everything in that file is in the crate root. A crate that generates an executable
2523+
defines a `main` function inside its root, as we've done here.
2524+
2525+
Let's define a new module inside our crate. Edit `src/main.rs` to look
2526+
like this:
2527+
2528+
```
2529+
fn main() {
2530+
println!("Hello, world!");
2531+
}
2532+
2533+
mod hello {
2534+
fn print_hello() {
2535+
println!("Hello, world!");
2536+
}
2537+
}
2538+
```
2539+
2540+
We now have a module named `hello` inside of our crate root. Modules use
2541+
`snake_case` naming, like functions and variable bindings.
2542+
2543+
Inside the `hello` module, we've defined a `print_hello` function. This will
2544+
also print out our hello world message. Modules allow you to split up your
2545+
program into nice neat boxes of functionality, grouping common things together,
2546+
and keeping different things apart. It's kinda like having a set of shelves:
2547+
a place for everything and everything in its place.
2548+
2549+
To call our `print_hello` function, we use the double colon (`::`):
2550+
2551+
```{rust,ignore}
2552+
hello::print_hello();
2553+
```
2554+
2555+
You've seen this before, with `io::stdin()` and `rand::random()`. Now you know
2556+
how to make your own. However, crates and modules have rules about
2557+
**visibility**, which controls who exactly may use the functions defined in a
2558+
given module. By default, everything in a module is private, which means that
2559+
it can only be used by other functions in the same module. This will not
2560+
compile:
2561+
2562+
```{rust,ignore}
2563+
fn main() {
2564+
hello::print_hello();
2565+
}
2566+
2567+
mod hello {
2568+
fn print_hello() {
2569+
println!("Hello, world!");
2570+
}
2571+
}
2572+
```
2573+
2574+
It gives an error:
2575+
2576+
```{notrust,ignore}
2577+
Compiling modules v0.1.0 (file:/home/you/projects/modules)
2578+
src/modules.rs:2:5: 2:23 error: function `print_hello` is private
2579+
src/modules.rs:2 hello::print_hello();
2580+
^~~~~~~~~~~~~~~~~~
2581+
```
2582+
2583+
To make it public, we use the `pub` keyword:
2584+
2585+
```{rust}
2586+
fn main() {
2587+
hello::print_hello();
2588+
}
2589+
2590+
mod hello {
2591+
pub fn print_hello() {
2592+
println!("Hello, world!");
2593+
}
2594+
}
2595+
```
2596+
2597+
This will work:
2598+
2599+
```{notrust,ignore}
2600+
$ cargo build
2601+
Compiling modules v0.1.0 (file:/home/you/projects/modules)
2602+
$
2603+
```
2604+
2605+
Before we move on, let me show you one more Cargo command: `run`. `cargo run`
2606+
is kind of like `cargo build`, but it also then runs the produced exectuable.
2607+
Try it out:
2608+
2609+
```{notrust,ignore}
2610+
$ cargo run
2611+
Compiling modules v0.1.0 (file:/home/steve/tmp/modules)
2612+
Running `target/modules`
2613+
Hello, world!
2614+
$
2615+
```
2616+
2617+
Nice!
2618+
2619+
There's a common pattern when you're building an executable: you build both an
2620+
executable and a library, and put most of your logic in the library. That way,
2621+
other programs can use that library to build their own functionality.
2622+
2623+
Let's do that with our project. If you remember, libraries and executables
2624+
are both crates, so while our project has one crate now, let's make a second:
2625+
one for the library, and one for the executable.
2626+
2627+
To make the second crate, open up `src/lib.rs` and put this code in it:
2628+
2629+
```{rust}
2630+
mod hello {
2631+
pub fn print_hello() {
2632+
println!("Hello, world!");
2633+
}
2634+
}
2635+
```
2636+
2637+
And change your `src/main.rs` to look like this:
2638+
2639+
```{rust,ignore}
2640+
extern crate modules;
2641+
2642+
fn main() {
2643+
modules::hello::print_hello();
2644+
}
2645+
```
2646+
2647+
There's been a few changes. First, we moved our `hello` module into its own
2648+
file, `src/lib.rs`. This is the file that Cargo expects a library crate to
2649+
be named, by convention.
2650+
2651+
Next, we added an `extern crate modules` to the top of our `src/main.rs`. This,
2652+
as you can guess, lets Rust know that our crate relies on another, external
2653+
crate. We also had to modify our call to `print_hello`: now that it's in
2654+
another crate, we need to first specify the crate, then the module inside of it,
2655+
then the function name.
2656+
2657+
This doesn't _quite_ work yet. Try it:
2658+
2659+
```{notrust,ignore}
2660+
$ cargo build
2661+
Compiling modules v0.1.0 (file:/home/you/projects/modules)
2662+
/home/you/projects/modules/src/lib.rs:2:5: 4:6 warning: code is never used: `print_hello`, #[warn(dead_code)] on by default
2663+
/home/you/projects/modules/src/lib.rs:2 pub fn print_hello() {
2664+
/home/you/projects/modules/src/lib.rs:3 println!("Hello, world!");
2665+
/home/you/projects/modules/src/lib.rs:4 }
2666+
/home/you/projects/modules/src/main.rs:4:5: 4:32 error: function `print_hello` is private
2667+
/home/you/projects/modules/src/main.rs:4 modules::hello::print_hello();
2668+
^~~~~~~~~~~~~~~~~~~~~~~~~~~
2669+
error: aborting due to previous error
2670+
Could not compile `modules`.
2671+
```
2672+
2673+
First, we get a warning that some code is never used. Odd. Next, we get an error:
2674+
`print_hello` is private, so we can't call it. Notice that the first error came
2675+
from `src/lib.rs`, and the second came from `src/main.rs`: cargo is smart enough
2676+
to build it all with one command. Also, after seeing the second error, the warning
2677+
makes sense: we never actually call `hello_world`, because we're not allowed to!
2678+
2679+
Just like modules, crates also have private visibility by default. Any modules
2680+
inside of a crate can only be used by other modules in the crate, unless they
2681+
use `pub`. In `src/lib.rs`, change this line:
2682+
2683+
```{rust,ignore}
2684+
mod hello {
2685+
```
2686+
2687+
To this:
2688+
2689+
```{rust,ignore}
2690+
pub mod hello {
2691+
```
2692+
2693+
And everything should work:
2694+
2695+
```{notrust,ignore}
2696+
$ cargo run
2697+
Compiling modules v0.1.0 (file:/home/you/projects/modules)
2698+
Running `target/modules`
2699+
Hello, world!
2700+
```
2701+
2702+
Let's do one more thing: add a `goodbye` module as well. Imagine a `src/lib.rs`
2703+
that looks like this:
2704+
2705+
```{rust,ignore}
2706+
pub mod hello {
2707+
pub fn print_hello() {
2708+
println!("Hello, world!");
2709+
}
2710+
}
2711+
2712+
pub mod goodbye {
2713+
pub fn print_goodbye() {
2714+
println!("Goodbye for now!");
2715+
}
2716+
}
2717+
```
2718+
2719+
Now, these two modules are pretty small, but imagine we've written a real, large
2720+
program: they could both be huge. So maybe we want to move them into their own
2721+
files. We can do that pretty easily, and there are two different conventions
2722+
for doing it. Let's give each a try. First, make `src/lib.rs` look like this:
2723+
2724+
```{rust,ignore}
2725+
pub mod hello;
2726+
pub mod goodbye;
2727+
```
2728+
2729+
This tells Rust that this crate has two public modules: `hello` and `goodbye`.
2730+
2731+
Next, make a `src/hello.rs` that contains this:
2732+
2733+
```{rust,ignore}
2734+
pub fn print_hello() {
2735+
println!("Hello, world!");
2736+
}
2737+
```
2738+
2739+
When we include a module like this, we don't need to make the `mod` declaration,
2740+
it's just understood. This helps prevent 'rightward drift': when you end up
2741+
indenting so many times that your code is hard to read.
2742+
2743+
Finally, make a new directory, `src/goodbye`, and make a new file in it,
2744+
`src/goodbye/mod.rs`:
2745+
2746+
```{rust,ignore}
2747+
pub fn print_goodbye() {
2748+
println!("Bye for now!");
2749+
}
2750+
```
2751+
2752+
Same deal, but we can make a folder with a `mod.rs` instead of `mod_name.rs` in
2753+
the same directory. If you have a lot of modules, nested folders can make
2754+
sense. For example, if the `goodbye` module had its _own_ modules inside of
2755+
it, putting all of that in a folder helps keep our directory structure tidy.
2756+
And in fact, if you place the modules in separate files, they're required to be
2757+
in separate folders.
2758+
2759+
This should all compile as usual:
2760+
2761+
```{notrust,ignore}
2762+
$ cargo build
2763+
Compiling modules v0.1.0 (file:/home/you/projects/modules)
2764+
$
2765+
```
2766+
2767+
We've seen how the `::` operator can be used to call into modules, but when
2768+
we have deep nesting like `modules::hello::say_hello`, it can get tedious.
2769+
That's why we have the `use` keyword.
2770+
2771+
`use` allows us to bring certain names into another scope. For example, here's
2772+
our main program:
2773+
2774+
```{rust,ignore}
2775+
extern crate modules;
2776+
2777+
fn main() {
2778+
modules::hello::print_hello();
2779+
}
2780+
```
2781+
2782+
We could instead write this:
2783+
2784+
```{rust,ignore}
2785+
extern crate modules;
2786+
2787+
use modules::hello::print_hello;
2788+
2789+
fn main() {
2790+
print_hello();
2791+
}
2792+
```
2793+
2794+
By bringing `print_hello` into scope, we don't need to qualify it anymore. However,
2795+
it's considered proper style to do write this code like like this:
2796+
2797+
```{rust,ignore}
2798+
extern crate modules;
2799+
2800+
use modules::hello;
2801+
2802+
fn main() {
2803+
hello::print_hello();
2804+
}
2805+
```
2806+
2807+
By just bringing the module into scope, we can keep one level of namespacing.
24682808

24692809
# Testing
24702810

2471-
attributes
2811+
## Attributes
24722812

2473-
stability markers
2813+
## Stability Markers
24742814

2475-
# Crates and Modules
2815+
# Pointers
24762816

2477-
visibility
2817+
# Lambdas
2818+
2819+
# iterators
24782820

24792821

24802822
# Generics

0 commit comments

Comments
 (0)