]> git.lizzy.rs Git - rust.git/commitdiff
Rewrote module tutorial
authorMarvin Löbel <loebel.marvin@gmail.com>
Fri, 23 Aug 2013 20:11:44 +0000 (22:11 +0200)
committerMarvin Löbel <loebel.marvin@gmail.com>
Tue, 27 Aug 2013 02:15:11 +0000 (04:15 +0200)
doc/tutorial.md

index c8136605aaede98b561c71696ccd870c00e50cb5..051de260a098c0d6b38b71fc5ad315ed39cb4519 100644 (file)
@@ -2251,237 +2251,665 @@ The full list of derivable traits is `Eq`, `TotalEq`, `Ord`,
 `TotalOrd`, `Encodable` `Decodable`, `Clone`, `DeepClone`,
 `IterBytes`, `Rand`, `Zero`, and `ToStr`.
 
-# Modules and crates
+# Crates and the module system
 
-The Rust namespace is arranged in a hierarchy of modules. Each source
-(.rs) file represents a single module and may in turn contain
-additional modules.
+Rust's module system is very powerful, but because of that also somewhat complex.
+Nevertheless, this section will try to explain every important aspect of it.
+
+## Crates
+
+In order to speak about the module system, we first need to define the medium it exists in:
+
+Let's say you've written a program or a library, compiled it, and got the resulting binary.
+In Rust, the content of all source code that the compiler directly had to compile in order to end up with
+that binary is collectively called a 'crate'.
+
+For example, for a simple hello world program your crate only consists of this code:
+
+~~~~
+// main.rs
+fn main() {
+    println("Hello world!");
+}
+~~~~
+
+A crate is also the unit of independent compilation in Rust: `rustc` always compiles a single crate at a time,
+from which it produces either a library or an executable.
+
+Note that merely using an already compiled library in your code does not make it part of your crate.
+
+## The module hierarchy
+
+For every crate, all the code in it is arranged in a hierarchy of modules starting with a single
+root module. That root module is called the 'crate root'.
+
+All modules in a crate below the crate root are declared with the `mod` keyword:
 
 ~~~~
+// This is the crate root
+
 mod farm {
-    pub fn chicken() -> &str { "cluck cluck" }
-    pub fn cow() -> &str { "mooo" }
+    // This is the body of module 'farm' declared in the crate root.
+
+    fn chicken() { println("cluck cluck"); }
+    fn cow() { println("mooo"); }
+
+    mod barn {
+        // Body of module 'barn'
+
+        fn hay() { println("..."); }
+    }
 }
 
 fn main() {
-    println(farm::chicken());
+    println("Hello farm!");
 }
 ~~~~
 
-The contents of modules can be imported into the current scope
-with the `use` keyword, optionally giving it an alias. `use`
-may appear at the beginning of crates, `mod`s, `fn`s, and other
-blocks.
+As you can see, your module hierarchy is now three modules deep: There is the crate root, which contains your `main()`
+function, and the module `farm`. The module `farm` also contains two functions and a third module `barn`,
+which contains a function `hay`.
 
-~~~
-# mod farm { pub fn chicken() { } }
-# fn main() {
-// Bring `chicken` into scope
-use farm::chicken;
+(In case you already stumbled over `extern mod`: It isn't directly related to a bare `mod`, we'll get to it later. )
+
+## Paths and visibility
 
-fn chicken_farmer() {
-    // The same, but name it `my_chicken`
-    use my_chicken = farm::chicken;
-    ...
-# my_chicken();
+We've now defined a nice module hierarchy. But how do we access the items in it from our `main` function?
+One way to do it is to simply fully qualifying it:
+
+~~~~ {.xfail-test}
+mod farm {
+    fn chicken() { println("cluck cluck"); }
+    // ...
 }
-# chicken();
-# }
-~~~
 
-These farm animal functions have a new keyword, `pub`, attached to
-them. The `pub` keyword modifies an item's visibility, making it
-visible outside its containing module. An expression with `::`, like
-`farm::chicken`, can name an item outside of its containing
-module. Items, such as those declared with `fn`, `struct`, `enum`,
-`type`, or `static`, are module-private by default.
+fn main() {
+    println("Hello chicken!");
+
+    ::farm::chicken(); // Won't compile yet, see further down
+}
+~~~~
+
+The `::farm::chicken` construct is what we call a 'path'.
+
+Because it's starting with a `::`, it's also a 'global path',
+which qualifies an item by its full path in the module hierarchy
+relative to the crate root.
+
+If the path were to start with a regular identifier, like `farm::chicken`, it would be
+a 'local path' instead. We'll get to them later.
+
+Now, if you actually tried to compile this code example, you'll notice
+that you get a `unresolved name: 'farm::chicken'` error. That's because per default,
+items (`fn`, `struct`, `static`, `mod`, ...) are only visible inside the module
+they are defined in.
+
+To make them visible outside their containing modules, you need to mark them _public_ with `pub`:
+
+~~~~
+mod farm {
+    pub fn chicken() { println("cluck cluck"); }
+    pub fn cow() { println("mooo"); }
+    // ...
+}
+
+fn main() {
+    println("Hello chicken!");
+    ::farm::chicken(); // This compiles now
+}
+~~~~
 
 Visibility restrictions in Rust exist only at module boundaries. This
 is quite different from most object-oriented languages that also
 enforce restrictions on objects themselves. That's not to say that
 Rust doesn't support encapsulation: both struct fields and methods can
 be private. But this encapsulation is at the module level, not the
-struct level. Note that fields and methods are _public_ by default.
+struct level.
+
+For convenience, fields are _public_ by default, and can be made _private_ with the `priv` keyword:
 
 ~~~
-pub mod farm {
+mod farm {
 # pub type Chicken = int;
-# type Cow = int;
 # struct Human(int);
 # impl Human { fn rest(&self) { } }
-# pub fn make_me_a_farm() -> Farm { Farm { chickens: ~[], cows: ~[], farmer: Human(0) } }
+# pub fn make_me_a_farm() -> Farm { Farm { chickens: ~[], farmer: Human(0) } }
     pub struct Farm {
         priv chickens: ~[Chicken],
-        priv cows: ~[Cow],
         farmer: Human
     }
 
     impl Farm {
         fn feed_chickens(&self) { ... }
-        fn feed_cows(&self) { ... }
         pub fn add_chicken(&self, c: Chicken) { ... }
     }
 
     pub fn feed_animals(farm: &Farm) {
         farm.feed_chickens();
-        farm.feed_cows();
     }
 }
 
 fn main() {
-     let f = make_me_a_farm();
-     f.add_chicken(make_me_a_chicken());
-     farm::feed_animals(&f);
-     f.farmer.rest();
+    let f = make_me_a_farm();
+    f.add_chicken(make_me_a_chicken());
+    farm::feed_animals(&f);
+    f.farmer.rest();
+
+    // This wouldn't compile because both are private:
+    // f.feed_chickens();
+    // let chicken_counter = f.chickens.len();
 }
 # fn make_me_a_farm() -> farm::Farm { farm::make_me_a_farm() }
 # fn make_me_a_chicken() -> farm::Chicken { 0 }
 ~~~
 
-## Crates
+> ***Note:*** Visibility rules are currently buggy and not fully defined, you might have to add or remove `pub` along a path until it works.
 
-The unit of independent compilation in Rust is the crate: rustc
-compiles a single crate at a time, from which it produces either a
-library or an executable.
-
-When compiling a single `.rs` source file, the file acts as the whole crate.
-You can compile it with the `--lib` compiler switch to create a shared
-library, or without, provided that your file contains a `fn main`
-somewhere, to create an executable.
-
-Larger crates typically span multiple files and are, by convention,
-compiled from a source file with the `.rc` extension, called a *crate file*.
-The crate file extension distinguishes source files that represent
-crates from those that do not, but otherwise source files and crate files are identical.
-
-A typical crate file declares attributes associated with the crate that
-may affect how the compiler processes the source.
-Crate attributes specify metadata used for locating and linking crates,
-the type of crate (library or executable),
-and control warning and error behavior,
-among other things.
-Crate files additionally declare the external crates they depend on
-as well as any modules loaded from other files.
-
-~~~~ { .xfail-test }
-// Crate linkage metadata
-#[link(name = "farm", vers = "2.5", author = "mjh")];
+## Files and modules
 
-// Make a library ("bin" is the default)
-#[crate_type = "lib"];
+One important aspect about Rusts module system is that source files are not important:
+You define a module hierarchy, populate it with all your definitions, define visibility,
+maybe put in a `fn main()`, and that's it: No need to think about source files.
 
-// Turn on a warning
-#[warn(non_camel_case_types)]
+The only file that's relevant is the one that contains the body of your crate root,
+and it's only relevant because you have to pass that file to `rustc` to compile your crate.
 
-// Link to the standard library
-extern mod std;
+And in principle, that's all you need: You can write any Rust program as one giant source file that contains your
+crate root and everything below it in `mod ... { ... }` declarations.
+
+However, in practice you usually want to split you code up into multiple source files to make it more manageable.
+In order to do that, Rust allows you to move the body of any module into it's own source file, which works like this:
 
-// Load some modules from other files
-mod cow;
-mod chicken;
-mod horse;
+If you declare a module without its body, like `mod foo;`, the compiler will look for the
+files `foo.rs` and `foo/mod.rs`. If it finds either, it uses the content of that file as the body of the module.
+If it finds both, that's a compile error.
+
+So, if we want to move the content of `mod farm` into it's own file, it would look like this:
+
+~~~~ {.ignore}
+// main.rs - contains body of the crate root
+mod farm; // Compiler will look for 'farm.rs' and 'farm/mod.rs'
 
 fn main() {
-    ...
+    println("Hello farm!");
+    ::farm::cow();
 }
 ~~~~
 
-Compiling this file will cause `rustc` to look for files named
-`cow.rs`, `chicken.rs`, and `horse.rs` in the same directory as the
-`.rc` file, compile them all together, and, based on the presence of
-the `crate_type = "lib"` attribute, output a shared library or an
-executable. (If the line `#[crate_type = "lib"];` was omitted,
-`rustc` would create an executable.)
+~~~~
+// farm.rs - contains body of module 'farm' in the crate root
+pub fn chicken() { println("cluck cluck"); }
+pub fn cow() { println("mooo"); }
 
-The `#[link(...)]` attribute provides meta information about the
-module, which other crates can use to load the right module. More
-about that later.
+pub mod barn {
+    pub fn hay() { println("..."); }
+}
+# fn main() { }
+~~~~
 
-To have a nested directory structure for your source files, you can
-nest mods:
+So, in short `mod foo;` is just syntactic sugar for `mod foo { /* include content of foo.rs or foo/mod.rs here */ }`.
 
-~~~~ {.ignore}
-mod poultry {
-    mod chicken;
-    mod turkey;
+This also means that having two or more identical `mod foo;` somewhere
+in your crate hierarchy is generally a bad idea,
+just like copy-and-paste-ing a module into two or more places is one.
+Both will result in duplicate and mutually incompatible definitions.
+
+The directory the compiler looks in for those two files is determined by starting with
+the same directory as the source file that contains the `mod foo;` declaration, and concatenating to that a
+path equivalent to the relative path of all nested `mod { ... }` declarations the `mod foo;` is contained in, if any.
+
+For example, given a file with this module body:
+
+~~~ {.ignore}
+// src/main.rs
+mod plants;
+mod fungi;
+mod animals {
+    mod fish;
+    mod mammals {
+        mod humans;
+    }
+}
+~~~
+
+The compiler would then try all these files:
+
+~~~ {.notrust}
+src/plants.rs
+src/plants/mod.rs
+
+src/fungi.rs
+src/fungi/mod.rs
+
+src/animals/fish.rs
+src/animals/fish/mod.rs
+
+src/animals/mammals/humans.rs
+src/animals/mammals/humans/mod.rs
+~~~
+
+These rules per default result in any directory structure mirroring
+the crates's module hierarchy, and allow you to have both small modules that only need
+to consist of one source file, and big modules that group the source files of submodules together.
+
+If you need to circumvent those defaults, you can also overwrite the path a `mod foo;` would take:
+
+~~~ {.ignore}
+#[path="../../area51/classified.rs"]
+mod alien;
+~~~
+
+## Importing names into the local scope
+
+Always referring to definitions in other modules with their global
+path gets old really fast, so Rust has a way to import
+them into the local scope of your module: `use`-statements.
+
+They work like this: At the beginning of any module body, `fn` body, or any other block
+you can write a list of `use`-statements, consisting of the keyword `use` and a __global path__ to an item
+without the `::` prefix. For example, this imports `cow` into the local scope:
+
+~~~
+use farm::cow;
+# mod farm { pub fn cow() { println("I'm a hidden ninja cow!") } }
+# fn main() { cow() }
+~~~
+
+The path you give to `use` is per default global, meaning relative to the crate root,
+no matter how deep the module hierarchy is, or whether the module body it's written in
+is contained in its own file (remember: files are irrelevant).
+
+This is different to other languages, where you often only find a single import construct that combines the semantic
+of `mod foo;` and `use`-statements, and which tend to work relative to the source file or use an absolute file path
+- Rubys `require` or C/C++'s `#include` come to mind.
+
+However, it's also possible to import things relative to the module of the `use`-statement:
+Adding a `super::` in front of the path will start in the parent module,
+while adding a `self::` prefix will start in the current module:
+
+~~~
+# mod workaround {
+# pub fn some_parent_item(){ println("...") }
+# mod foo {
+use super::some_parent_item;
+use self::some_child_module::some_item;
+# pub fn bar() { some_parent_item(); some_item() }
+# pub mod some_child_module { pub fn some_item() {} }
+# }
+# }
+~~~
+
+Again - relative to the module, not to the file.
+
+Imports are also shadowed by local definitions:
+For each name you mention in a module/block, `rust`
+will first look at all items that are defined locally,
+and only if that results in no match look at items you brought in
+scope with corresponding `use` statements.
+
+~~~ {.ignore}
+# // XXX: Allow unused import in doc test
+use farm::cow;
+// ...
+# mod farm { pub fn cow() { println("Hidden ninja cow is hidden.") } }
+fn cow() { println("Mooo!") }
+
+fn main() {
+    cow() // resolves to the locally defined cow() function
 }
+~~~
+
+To make this behavior more obvious, the rule has been made that `use`-statement always need to be written
+before any declaration, like in the example above. This is a purely artificial rule introduced
+because people always assumed they shadowed each other based on order, despite the fact that all items in rust are
+mutually recursive, order independent definitions.
+
+One odd consequence of that rule is that `use` statements also go in front of any `mod` declaration,
+even if they refer to things inside them:
+
+~~~
+use farm::cow;
+mod farm {
+    pub fn cow() { println("Moooooo?") }
+}
+
+fn main() { cow() }
+~~~
+
+This is what our `farm` example looks like with `use` statements:
+
 ~~~~
+use farm::chicken;
+use farm::cow;
+use farm::barn;
 
-The compiler will now look for `poultry/chicken.rs` and
-`poultry/turkey.rs`, and export their content in `poultry::chicken`
-and `poultry::turkey`. You can also provide a `poultry.rs` to add
-content to the `poultry` module itself.
+mod farm {
+    pub fn chicken() { println("cluck cluck"); }
+    pub fn cow() { println("mooo"); }
 
-## Using other crates
+    pub mod barn {
+        pub fn hay() { println("..."); }
+    }
+}
 
-The `extern mod` directive lets you use a crate (once it's been
-compiled into a library) from inside another crate. `extern mod` can
-appear at the top of a crate file or at the top of modules. It will
-cause the compiler to look in the library search path (which you can
-extend with the `-L` switch) for a compiled Rust library with the
-right name, then add a module with that crate's name into the local
-scope.
+fn main() {
+    println("Hello farm!");
 
-For example, `extern mod std` links the [standard library].
+    // Can now refer to those names directly:
+    chicken();
+    cow();
+    barn::hay();
+}
+~~~~
 
-[standard library]: std/index.html
+And here an example with multiple files:
+~~~{.ignore}
+// a.rs - crate root
+use b::foo;
+mod b;
+fn main() { foo(); }
+~~~
+~~~{.ignore}
+// b.rs
+use b::c::bar;
+pub mod c;
+pub fn foo() { bar(); }
+~~~
+~~~
+// c.rs
+pub fn bar() { println("Baz!"); }
+~~~
 
-When a comma-separated list of name/value pairs appears after `extern
-mod`, the compiler front-end matches these pairs against the
-attributes provided in the `link` attribute of the crate file. The
-front-end will only select this crate for use if the actual pairs
-match the declared attributes. You can provide a `name` value to
-override the name used to search for the crate.
+There also exist two short forms for importing multiple names at once:
 
-Our example crate declared this set of `link` attributes:
+1. Explicit mention multiple names as the last element of an `use` path:
+~~~
+use farm::{chicken, cow};
+# mod farm {
+#     pub fn cow() { println("Did I already mention how hidden and ninja I am?") }
+#     pub fn chicken() { println("I'm Bat-chicken, guardian of the hidden tutorial code.") }
+# }
+# fn main() { cow(); chicken() }
+~~~
+
+2. Import everything in a module with a wildcard:
+~~~
+use farm::*;
+# mod farm {
+#     pub fn cow() { println("Bat-chicken? What a stupid name!") }
+#     pub fn chicken() { println("Says the 'hidden ninja' cow.") }
+# }
+# fn main() { cow(); chicken() }
+~~~
+
+However, that's not all. You can also rename an item while you're bringing it into scope:
+
+~~~
+use egg_layer = farm::chicken;
+# mod farm { pub fn chicken() { println("Laying eggs is fun!")  } }
+// ...
+
+fn main() {
+    egg_layer();
+}
+~~~
+
+In general, `use` creates an local alias:
+An alternate path and a possibly different name to access the same item,
+whiteout touching the original, and with both being interchangeable.
+
+## Reexporting names
+
+It is also possible to reexport items to be accessible under your module.
+
+For that, you write `pub use`:
+
+~~~
+mod farm {
+    pub use self::barn::hay;
+
+    pub fn chicken() { println("cluck cluck"); }
+    pub fn cow() { println("mooo"); }
+
+    mod barn {
+        pub fn hay() { println("..."); }
+    }
+}
+
+fn main() {
+    farm::chicken();
+    farm::cow();
+    farm::hay();
+}
+~~~
+
+Just like in normal `use` statements, the exported names
+merely represent an alias to the same thing and can also be renamed.
+
+The above example also demonstrate what you can use `pub use` for:
+The nested `barn` module is private, but the `pub use` allows users
+of the module `farm` to access a function from `barn` without needing
+to know that `barn` exists.
+
+In other words, you can use them to decouple an public api from their internal implementation.
+
+## Using libraries
+
+So far we've only talked about how to define and structure your own crate.
+
+However, most code out there will want to use preexisting libraries,
+as there really is no reason to start from scratch each time you start a new project.
+
+In Rust terminology, we need a way to refer to other crates.
+
+For that, Rust offers you the `extern mod` declaration:
+
+~~~
+extern mod extra;
+// extra ships with Rust, you'll find more details further down.
+
+fn main() {
+    // The rational number '1/2':
+    let one_half = ::extra::rational::Ratio::new(1, 2);
+}
+~~~
+
+Despite its name, `extern mod` is a distinct construct from regular `mod` declarations:
+A statement of the form `extern mod foo;` will cause `rustc` to search for the crate `foo`,
+and if it finds a matching binary it lets you use it from inside your crate.
+
+The effect it has on your module hierarchy mirrors aspects of both `mod` and `use`:
+
+- Like `mod`, it causes `rustc` to actually emit code:
+  The linkage information the binary needs to use the library `foo`.
+
+- But like `use`, all `extern mod` statements that refer to the same library are interchangeable,
+  as each one really just presents an alias to an external module (the crate root of the library your linking against).
+
+Remember how `use`-statements have to go before local declarations because the latter shadows the former?
+Well, `extern mod` statements also have their own rules in that regard:
+Both `use` and local declarations can shadow them, so the rule is that `extern mod` has to go in front
+of both `use` and local declarations.
+
+Which can result in something like this:
+
+~~~
+extern mod extra;
+
+use farm::dog;
+use extra::rational::Ratio;
+
+mod farm {
+    pub fn dog() { println("woof"); }
+}
+
+fn main() {
+    farm::dog();
+    let a_third = Ratio::new(1, 3);
+}
+~~~
+
+It's a bit weird, but it's the result of shadowing rules that have been set that way because
+they model most closely what people expect to shadow.
+
+## Package ids
+
+If you use `extern mod`, per default `rustc` will look for libraries in the the library search path (which you can
+extend with the `-L` switch).
+
+However, Rust also ships with rustpkg, a package manager that is able to automatically download and build
+libraries if you use it for building your crate. How it works is explained [here][rustpkg],
+but for this tutorial it's only important to know that you can optionally annotate an
+`extern mod` statement with an package id that rustpkg can use to identify it:
+
+~~~ {.ignore}
+extern mod rust = "github.com/mozilla/rust"; // pretend Rust is an simple library
+~~~
+
+[rustpkg]: rustpkg.html
+
+## Crate metadata and settings
+
+For every crate you can define a number of metadata items, such as link name, version or author.
+You can also toggle settings that have crate-global consequences. Both mechanism
+work by providing attributes in the crate root.
+
+For example, Rust uniquely identifies crates by their link metadate, which includes
+the link name and the version. It also hashes the filename and the symbols in a binary
+based on the link metadata, allowing you to use two different versions of the same library in a crate
+without conflict.
+
+Therefor, if you plan to compile your crate as a library, you should annotate it with that information:
 
 ~~~~
-#[link(name = "farm", vers = "2.5", author = "mjh")];
+// lib.rs
+
+# #[crate_type = "lib"];
+// Crate linkage metadata
+#[link(name = "farm", vers = "2.5")];
+
+// ...
+# pub fn farm() {}
 ~~~~
 
-Which you can then link with any (or all) of the following:
+You can also in turn require in a `extern mod` statement that certain link metadata items match some criteria.
+For that, Rust currently parses a comma-separated list of name/value pairs that appear after
+it, and ensures that they match the attributes provided in the `link` attribute of a crate file.
+This enables you to, eg, pick a a crate based on it's version number, or to link an library under an
+different name. For example, this two mod statements would both accept and select the crate define above:
 
 ~~~~ {.xfail-test}
-extern mod farm;
-extern mod my_farm (name = "farm", vers = "2.5");
-extern mod my_auxiliary_farm (name = "farm", author = "mjh");
+extern mod farm(vers = "2.5");
+extern mod my_farm(name = "farm", vers = "2.5");
+~~~~
+
+Other crate settings and metadata include things like enabling/disabling certain errors or warnings,
+or setting the crate type (library or executable) explicitly:
+
 ~~~~
+// lib.rs
+// ...
 
-If any of the requested metadata do not match, then the crate
-will not be compiled successfully.
+// This crate is a library ("bin" is the default)
+#[crate_type = "lib"];
+
+// Turn on a warning
+#[warn(non_camel_case_types)]
+# pub fn farm() {}
+~~~~
+
+If you're compiling your crate with `rustpkg`,
+link annotations will not be necessary, because they get
+inferred by `rustpkg` based on the Package id and naming conventions.
+
+
+> ***Note:*** The rules regarding link metadata, both as attributes and on `extern mod`,
+              as well as their interaction with `rustpkg`
+              are currently not clearly defined and will likely change in the future.
 
 ## A minimal example
 
-Now for something that you can actually compile yourself, we have
-these two files:
+Now for something that you can actually compile yourself.
+
+We define two crates, and use one of them as a library in the other.
 
 ~~~~
 // world.rs
-#[link(name = "world", vers = "1.0")];
-pub fn explore() -> &str { "world" }
+#[link(name = "world", vers = "0.42")];
+pub fn explore() -> &'static str { "world" }
 ~~~~
 
 ~~~~ {.xfail-test}
 // main.rs
 extern mod world;
-fn main() { println(~"hello " + world::explore()); }
+fn main() { println("hello " + world::explore()); }
 ~~~~
 
 Now compile and run like this (adjust to your platform if necessary):
 
 ~~~~ {.notrust}
-> rustc --lib world.rs  # compiles libworld-94839cbfe144198-1.0.so
+> rustc --lib world.rs  # compiles libworld-<HASH>-0.42.so
 > rustc main.rs -L .    # compiles main
 > ./main
 "hello world"
 ~~~~
 
-Notice that the library produced contains the version in the filename
-as well as an inscrutable string of alphanumerics. These are both
-part of Rust's library versioning scheme. The alphanumerics are
-a hash representing the crate metadata.
+Notice that the library produced contains the version in the file name
+as well as an inscrutable string of alphanumerics. As explained in the previous paragraph,
+these are both part of Rust's library versioning scheme. The alphanumerics are
+a hash representing the crates link metadata.
+
+## The standard library and the prelude
+
+While reading the examples in this tutorial, you might have asked yourself where all
+those magical predefined items like `println()` are coming from.
+
+The truth is, there's nothing magical about them: They are all defined normally
+in the `std` library, which is a crate that ships with Rust.
+
+The only magical thing that happens is that `rustc` automatically inserts this line into your crate root:
+
+~~~ {.ignore}
+extern mod std;
+~~~
+
+As well as this line into every module body:
+
+~~~ {.ignore}
+use std::prelude::*;
+~~~
+
+The role of the `prelude` module is to re-exports common definitions from `std`.
+
+This allows you to use common types and functions like `Option<T>` or `println`
+without needing to import them. And if you need something from `std` that's not in the prelude,
+you just have to import it with an `use` statement.
+
+For example, it re-exports `println` which is defined in `std::io::println`:
+
+~~~
+use puts = std::io::println;
+
+fn main() {
+    println("println is imported per default.");
+    puts("Doesn't hinder you from importing it under an different name yourself.");
+    ::std::io::println("Or from not using the automatic import.");
+}
+~~~
+
+Both auto-insertions can be disabled with an attribute if necessary:
+
+~~~
+// In the crate root:
+#[no_std];
+~~~
+
+~~~
+// In any module:
+#[no_implicit_prelude];
+~~~
 
-## The standard library
+## The standard library in detail
 
 The Rust standard library provides runtime features required by the language,
 including the task scheduler and memory allocators, as well as library
@@ -2499,24 +2927,9 @@ I/O abstractions ([`io`]), [containers] like [`hashmap`],
 common traits ([`kinds`], [`ops`], [`cmp`], [`num`],
 [`to_str`], [`clone`]), and complete bindings to the C standard library ([`libc`]).
 
-### Standard Library injection and the Rust prelude
-
-`std` is imported at the topmost level of every crate by default, as
-if the first line of each crate was
-
-    extern mod std;
-
-This means that the contents of std can be accessed from from any context
-with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`,
-etc.
-
-Additionally, `std` contains a `prelude` module that reexports many of the
-most common standard modules, types and traits. The contents of the prelude are
-imported into every *module* by default.  Implicitly, all modules behave as if
-they contained the following prologue:
-
-    use std::prelude::*;
+The full documentation for `std` can be found here: [standard library].
 
+[standard library]: std/index.html
 [`std`]: std/index.html
 [`bool`]: std/bool.html
 [tuples]: std/tuple.html
@@ -2543,6 +2956,18 @@ they contained the following prologue:
 [`clone`]: std/clone.html
 [`libc`]: std/libc.html
 
+## The extra library
+
+Rust also ships with the [extra library], an accumulation of
+useful things, that are however not important enough
+to deserve a place in the standard library.
+You can use them by linking to `extra` with an `extern mod extra;`.
+
+[extra library]: extra/index.html
+
+Right now `extra` contains those definitions directly, but in the future it will likely just
+re-export a bunch of 'officially blessed' crates that get managed with `rustpkg`.
+
 # What next?
 
 Now that you know the essentials, check out any of the additional
@@ -2554,7 +2979,7 @@ tutorials on individual topics.
 * [The foreign function interface][ffi]
 * [Containers and iterators](tutorial-container.html)
 
-There is further documentation on the [wiki].
+There is further documentation on the [wiki], however those tend to be even more out of date as this document.
 
 [borrow]: tutorial-borrowed-ptr.html
 [tasks]: tutorial-tasks.html