diff --git a/src/doc/reference.md b/src/doc/reference.md index c159f6164c205..d918a320e63a9 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -973,8 +973,7 @@ Use declarations support a number of convenient shortcuts: An example of `use` declarations: -``` -# #![feature(core)] +```rust use std::option::Option::{Some, None}; use std::collections::hash_map::{self, HashMap}; @@ -1031,16 +1030,17 @@ declarations. An example of what will and will not work for `use` items: ``` -# #![feature(core)] # #![allow(unused_imports)] -use foo::core::iter; // good: foo is at the root of the crate use foo::baz::foobaz; // good: foo is at the root of the crate mod foo { - extern crate core; - use foo::core::iter; // good: foo is at crate root -// use core::iter; // bad: core is not at the crate root + mod example { + pub mod iter {} + } + + use foo::example::iter; // good: foo is at crate root +// use example::iter; // bad: core is not at the crate root use self::baz::foobaz; // good: self refers to module 'foo' use foo::bar::foobar; // good: foo is at crate root @@ -1368,9 +1368,7 @@ a = Animal::Cat; Enumeration constructors can have either named or unnamed fields: -``` -# #![feature(struct_variant)] -# fn main() { +```rust enum Animal { Dog (String, f64), Cat { name: String, weight: f64 } @@ -1378,7 +1376,6 @@ enum Animal { let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2); a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 }; -# } ``` In this example, `Cat` is a _struct-like enum variant_, @@ -1718,17 +1715,6 @@ Functions within external blocks are declared in the same way as other Rust functions, with the exception that they may not have a body and are instead terminated by a semicolon. -``` -# #![feature(libc)] -extern crate libc; -use libc::{c_char, FILE}; - -extern { - fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; -} -# fn main() {} -``` - Functions within external blocks may be called by Rust code, just like functions defined in Rust. The Rust compiler automatically translates between the Rust ABI and the foreign ABI. @@ -1739,7 +1725,7 @@ By default external blocks assume that the library they are calling uses the standard C "cdecl" ABI. Other ABIs may be specified using an `abi` string, as shown here: -```{.ignore} +```ignore // Interface to the Windows API extern "stdcall" { } ``` @@ -3231,55 +3217,7 @@ expression. In a pattern whose head expression has an `enum` type, a placeholder (`_`) stands for a *single* data field, whereas a wildcard `..` stands for *all* the -fields of a particular variant. For example: - -``` -#![feature(box_patterns)] -#![feature(box_syntax)] -enum List { Nil, Cons(X, Box>) } - -fn main() { - let x: List = List::Cons(10, box List::Cons(11, box List::Nil)); - - match x { - List::Cons(_, box List::Nil) => panic!("singleton list"), - List::Cons(..) => return, - List::Nil => panic!("empty list") - } -} -``` - -The first pattern matches lists constructed by applying `Cons` to any head -value, and a tail value of `box Nil`. The second pattern matches _any_ list -constructed with `Cons`, ignoring the values of its arguments. The difference -between `_` and `..` is that the pattern `C(_)` is only type-correct if `C` has -exactly one argument, while the pattern `C(..)` is type-correct for any enum -variant `C`, regardless of how many arguments `C` has. - -Used inside an array pattern, `..` stands for any number of elements, when the -`advanced_slice_patterns` feature gate is turned on. This wildcard can be used -at most once for a given array, which implies that it cannot be used to -specifically match elements that are at an unknown distance from both ends of a -array, like `[.., 42, ..]`. If preceded by a variable name, it will bind the -corresponding slice to the variable. Example: - -``` -# #![feature(advanced_slice_patterns, slice_patterns)] -fn is_symmetric(list: &[u32]) -> bool { - match list { - [] | [_] => true, - [x, inside.., y] if x == y => is_symmetric(inside), - _ => false - } -} - -fn main() { - let sym = &[0, 1, 4, 2, 4, 1, 0]; - let not_sym = &[0, 1, 7, 2, 4, 1, 0]; - assert!(is_symmetric(sym)); - assert!(!is_symmetric(not_sym)); -} -``` +fields of a particular variant. A `match` behaves differently depending on whether or not the head expression is an [lvalue or an rvalue](#lvalues,-rvalues-and-temporaries). If the head @@ -3298,30 +3236,15 @@ the inside of the match. An example of a `match` expression: ``` -#![feature(box_patterns)] -#![feature(box_syntax)] -# fn process_pair(a: i32, b: i32) { } -# fn process_ten() { } - -enum List { Nil, Cons(X, Box>) } - -fn main() { - let x: List = List::Cons(10, box List::Cons(11, box List::Nil)); +let x = 1; - match x { - List::Cons(a, box List::Cons(b, _)) => { - process_pair(a, b); - } - List::Cons(10, _) => { - process_ten(); - } - List::Nil => { - return; - } - _ => { - panic!(); - } - } +match x { + 1 => println!("one"), + 2 => println!("two"), + 3 => println!("three"), + 4 => println!("four"), + 5 => println!("five"), + _ => println!("something else"), } ``` @@ -3334,28 +3257,12 @@ Subpatterns can also be bound to variables by the use of the syntax `variable @ subpattern`. For example: ``` -#![feature(box_patterns)] -#![feature(box_syntax)] - -enum List { Nil, Cons(u32, Box) } +let x = 1; -fn is_sorted(list: &List) -> bool { - match *list { - List::Nil | List::Cons(_, box List::Nil) => true, - List::Cons(x, ref r @ box List::Cons(_, _)) => { - match *r { - box List::Cons(y, _) => (x <= y) && is_sorted(&**r), - _ => panic!() - } - } - } -} - -fn main() { - let a = List::Cons(6, box List::Cons(7, box List::Cons(42, box List::Nil))); - assert!(is_sorted(&a)); +match x { + e @ 1 ... 5 => println!("got a range element {}", e), + _ => println!("anything"), } - ``` Patterns can also dereference pointers by using the `&`, `&mut` and `box` diff --git a/src/doc/trpl/README.md b/src/doc/trpl/README.md index 8d3a6ec39864c..dfe837285c877 100644 --- a/src/doc/trpl/README.md +++ b/src/doc/trpl/README.md @@ -165,7 +165,7 @@ fn main() { Rust has [move semantics][move] by default, so if we want to make a copy of some data, we call the `clone()` method. In this example, `y` is no longer a reference -to the vector stored in `x`, but a copy of its first element, `"hello"`. Now +to the vector stored in `x`, but a copy of its first element, `"Hello"`. Now that we don’t have a reference, our `push()` works just fine. [move]: move-semantics.html diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index f2d1666048d89..a179f8fa55e5e 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -14,7 +14,6 @@ * [Concurrency](concurrency.md) * [Error Handling](error-handling.md) * [FFI](ffi.md) - * [Deref coercions](deref-coercions.md) * [Syntax and Semantics](syntax-and-semantics.md) * [Variable Bindings](variable-bindings.md) * [Functions](functions.md) @@ -30,15 +29,15 @@ * [Move semantics](move-semantics.md) * [Enums](enums.md) * [Match](match.md) - * [Patterns](patterns.md) * [Structs](structs.md) + * [Patterns](patterns.md) * [Method Syntax](method-syntax.md) - * [Drop](drop.md) * [Vectors](vectors.md) * [Strings](strings.md) + * [Generics](generics.md) * [Traits](traits.md) * [Operators and Overloading](operators-and-overloading.md) - * [Generics](generics.md) + * [Drop](drop.md) * [if let](if-let.md) * [Trait Objects](trait-objects.md) * [Closures](closures.md) @@ -53,8 +52,9 @@ * [Casting between types](casting-between-types.md) * [Associated Types](associated-types.md) * [Unsized Types](unsized-types.md) + * [Deref coercions](deref-coercions.md) * [Macros](macros.md) - * [`unsafe` Code](unsafe-code.md) + * [Raw Pointers](raw-pointers.md) * [Nightly Rust](nightly-rust.md) * [Compiler Plugins](compiler-plugins.md) * [Inline Assembly](inline-assembly.md) diff --git a/src/doc/trpl/casting-between-types.md b/src/doc/trpl/casting-between-types.md index 8bb0ec6db0256..90731b64a38dc 100644 --- a/src/doc/trpl/casting-between-types.md +++ b/src/doc/trpl/casting-between-types.md @@ -1,3 +1,89 @@ % Casting Between Types -Coming Soon +Rust, with its focus on safety, provides two different ways of casting +different types between each other. The first, `as`, is for safe casts. +In contrast, `transmute` allows for arbitrary casting, and is one of the +most dangerous features of Rust! + +# `as` + +The `as` keyword does basic casting: + +```rust +let x: i32 = 5; + +let y = x as i64; +``` + +It only allows certain kinds of casting, however: + +```rust,ignore +let a = [0u8, 0u8, 0u8, 0u8]; + +let b = a as u32; // four eights makes 32 +``` + +This errors with: + +```text +error: non-scalar cast: `[u8; 4]` as `u32` +let b = a as u32; // four eights makes 32 + ^~~~~~~~ +``` + +It’s a ‘non-scalar cast’ because we have multiple values here: the four +elements of the array. These kinds of casts are very dangerous, because they +make assumptions about the way that multiple underlying strucutres are +implemented. For this, we need something more dangerous. + +# `transmute` + +The `transmute` function is provided by a [compiler intrinsic][intrinsics], and +what it does is very simple, but very scary. It tells Rust to treat a value of +one type as though it were another type. It does this regardless of the +typechecking system, and just completely trusts you. + +[intrinsic]: intrinsics.html + +In our previous example, we know that an array of four `u8`s represents a `u32` +properly, and so we want to do the cast. Using `transmute` instead of `as`, +Rust lets us: + +```rust +use std::mem; + +unsafe { + let a = [0u8, 0u8, 0u8, 0u8]; + + let b = mem::transmute::<[u8; 4], u32>(a); +} +``` + +We have to wrap the operation in an `unsafe` block, but this will compile +successfully. Technically, only the `mem::transmute` call itself needs to be in +the block, but it's nice in this case to enclose everything related, so you +know where to look. In this case, the details about `a` are also important, and +so they're in the block. You'll see code in either style, sometimes the context +is too far away, and wrapping all of the code in `unsafe` isn't a great idea. + +While `transmute` does very little checking, it will at least make sure that +the types are the same size. This errors: + +```rust,ignore +use std::mem; + +unsafe { + let a = [0u8, 0u8, 0u8, 0u8]; + + let b = mem::transmute::<[u8; 4], u64>(a); +} +``` + +with: + +```text +error: transmute called on types with different sizes: [u8; 4] (32 bits) to u64 +(64 bits) +``` + +Other than that, you're on your own! diff --git a/src/doc/trpl/enums.md b/src/doc/trpl/enums.md index 504bd099171ba..80ea25eb35ce9 100644 --- a/src/doc/trpl/enums.md +++ b/src/doc/trpl/enums.md @@ -1,11 +1,9 @@ % Enums -Finally, 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. These -can be used via their fully scoped names: `Character::Other` (more about `::` -below). +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. ```rust enum Character { @@ -14,14 +12,14 @@ enum Character { } ``` -Most normal types are allowed as the variant components of an `enum`. Here are -some examples: +Most types are allowed as the variant components of an `enum`. Here are some +examples: ```rust struct Empty; struct Color(i32, i32, i32); struct Length(i32); -struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 } +struct Stats { Health: i32, Mana: i32, Attack: i32, Defense: i32 } struct HeightDatabase(Vec); ``` @@ -30,12 +28,12 @@ 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. -As with structures, 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: +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} +```rust,ignore // These assignments both succeed let ten = Character::Digit(10); let four = Character::Digit(4); @@ -50,98 +48,21 @@ let four_is_smaller = four <= ten; let four_equals_ten = four == ten; ``` -This 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 -chapter. We don't know enough about Rust to implement equality yet, but we can -use the `Ordering` enum from the standard library, which does: +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: -``` -enum Ordering { - Less, - Equal, - Greater, -} -``` - -Because `Ordering` has already been defined for us, we will import it with the -`use` keyword. Here's an example of how it is used: - -```{rust} -use std::cmp::Ordering; - -fn cmp(a: i32, b: i32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} - -fn main() { - let x = 5; - let y = 10; - - let ordering = cmp(x, y); // ordering: Ordering - - if ordering == Ordering::Less { - println!("less"); - } else if ordering == Ordering::Greater { - println!("greater"); - } else if ordering == Ordering::Equal { - println!("equal"); - } -} -``` - -The `::` symbol is used to indicate a namespace. In this case, `Ordering` lives -in the `cmp` submodule of the `std` module. We'll talk more about modules later -in the guide. For now, all you need to know is that you can `use` things from -the standard library if you need them. - -Okay, let's talk about the actual code in the example. `cmp` is a function that -compares two things, and returns an `Ordering`. We return either -`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on -whether the first value is less than, greater than, or equal to the second. Note -that each variant of the `enum` is namespaced under the `enum` itself: it's -`Ordering::Greater`, not `Greater`. - -The `ordering` variable has the type `Ordering`, and so contains one of the -three values. We then do a bunch of `if`/`else` comparisons to check which -one it is. - -This `Ordering::Greater` notation is too long. Let's use another form of `use` -to import the `enum` variants instead. This will avoid full scoping: - -```{rust} -use std::cmp::Ordering::{self, Equal, Less, Greater}; - -fn cmp(a: i32, b: i32) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } -} - -fn main() { - let x = 5; - let y = 10; - - let ordering = cmp(x, y); // ordering: Ordering - - if ordering == Less { println!("less"); } - else if ordering == Greater { println!("greater"); } - else if ordering == Equal { println!("equal"); } -} +```rust,ignore +Character::Digit(10); +Hand::Digit; ``` -Importing variants is convenient and compact, but can also cause name conflicts, -so do this with caution. For this reason, it's normally considered better style -to `use` an enum rather than its variants directly. +Both variants are named `Digit`, but since they’re scoped to the `enum` name, -As you can see, `enum`s are quite a powerful tool for data representation, and -are even more useful when they're [generic][generics] across types. Before we -get to generics, though, let's talk about how to use enums with pattern -matching, a tool that will let us deconstruct sum types (the type theory term -for enums) like `Ordering` in a very elegant way that avoids all these messy -and brittle `if`/`else`s. +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. -[match]: ./match.html -[generics]: ./generics.html +[match]: match.html +[traits]: traits.html diff --git a/src/doc/trpl/generics.md b/src/doc/trpl/generics.md index 3e4e0a66eae05..517a6e6064253 100644 --- a/src/doc/trpl/generics.md +++ b/src/doc/trpl/generics.md @@ -1,31 +1,13 @@ % Generics Sometimes, when writing a function or data type, we may want it to work for -multiple types of arguments. For example, remember our `OptionalInt` type? +multiple types of arguments. Luckily, Rust has a feature that gives us a better +way: generics. Generics are called ‘parametric polymorphism’ in type theory, +which means that they are types or functions that have multiple forms (‘poly’ +is multiple, ‘morph’ is form) over a given parameter (‘parametric’). -```{rust} -enum OptionalInt { - Value(i32), - Missing, -} -``` - -If we wanted to also have an `OptionalFloat64`, we would need a new enum: - -```{rust} -enum OptionalFloat64 { - Valuef64(f64), - Missingf64, -} -``` - -This is really unfortunate. Luckily, Rust has a feature that gives us a better -way: generics. Generics are called *parametric polymorphism* in type theory, -which means that they are types or functions that have multiple forms (*poly* -is multiple, *morph* is form) over a given parameter (*parametric*). - -Anyway, enough with type theory declarations, let's check out the generic form -of `OptionalInt`. It is actually provided by Rust itself, and looks like this: +Anyway, enough with type theory, let’s check out some generic code. Rust’s +standard library provides a type, `Option`, that’s generic: ```rust enum Option { @@ -34,41 +16,40 @@ enum Option { } ``` -The `` part, which you've seen a few times before, indicates that this is +The `` part, which you’ve seen a few times before, indicates that this is a generic data type. Inside the declaration of our enum, wherever we see a `T`, -we substitute that type for the same type used in the generic. Here's an +we substitute that type for the same type used in the generic. Here’s an example of using `Option`, with some extra type annotations: -```{rust} +```rust let x: Option = Some(5); ``` In the type declaration, we say `Option`. Note how similar this looks to `Option`. So, in this particular `Option`, `T` has the value of `i32`. On the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5`. -Since that's an `i32`, the two sides match, and Rust is happy. If they didn't -match, we'd get an error: +Since that’s an `i32`, the two sides match, and Rust is happy. If they didn’t +match, we’d get an error: -```{rust,ignore} +```rust,ignore let x: Option = Some(5); // error: mismatched types: expected `core::option::Option`, // found `core::option::Option<_>` (expected f64 but found integral variable) ``` -That doesn't mean we can't make `Option`s that hold an `f64`! They just have to -match up: +That doesn’t mean we can’t make `Option`s that hold an `f64`! They just have +to match up: -```{rust} +```rust let x: Option = Some(5); let y: Option = Some(5.0f64); ``` This is just fine. One definition, multiple uses. -Generics don't have to only be generic over one type. Consider Rust's built-in -`Result` type: +Generics don’t have to only be generic over one type. Consider another type from Rust’s standard library that’s similar, `Result`: -```{rust} +```rust enum Result { Ok(T), Err(E), @@ -76,9 +57,9 @@ enum Result { ``` This type is generic over _two_ types: `T` and `E`. By the way, the capital letters -can be any letter you'd like. We could define `Result` as: +can be any letter you’d like. We could define `Result` as: -```{rust} +```rust enum Result { Ok(A), Err(Z), @@ -86,92 +67,58 @@ enum Result { ``` if we wanted to. Convention says that the first generic parameter should be -`T`, for 'type,' and that we use `E` for 'error.' Rust doesn't care, however. +`T`, for ‘type’, and that we use `E` for ‘error’. Rust doesn’t care, however. The `Result` type is intended to be used to return the result of a -computation, and to have the ability to return an error if it didn't work out. -Here's an example: - -```{rust} -let x: Result = Ok(2.3f64); -let y: Result = Err("There was an error.".to_string()); -``` +computation, and to have the ability to return an error if it didn’t work out. -This particular Result will return an `f64` if there's a success, and a -`String` if there's a failure. Let's write a function that uses `Result`: +## Generic functions -```{rust} -fn inverse(x: f64) -> Result { - if x == 0.0f64 { return Err("x cannot be zero!".to_string()); } +We can write functions that take generic types with a similar syntax: - Ok(1.0f64 / x) +```rust +fn takes_anything(x: T) { + // do something with x } ``` -We don't want to take the inverse of zero, so we check to make sure that we -weren't passed zero. If we were, then we return an `Err`, with a message. If -it's okay, we return an `Ok`, with the answer. +The syntax has two parts: the `` says “this function is generic over one +type, `T`”, and the `x: T` says “x has the type `T`.” -Why does this matter? Well, remember how `match` does exhaustive matches? -Here's how this function gets used: +Multiple arguments can have the same generic type: -```{rust} -# fn inverse(x: f64) -> Result { -# if x == 0.0f64 { return Err("x cannot be zero!".to_string()); } -# Ok(1.0f64 / x) -# } -let x = inverse(25.0f64); - -match x { - Ok(x) => println!("The inverse of 25 is {}", x), - Err(msg) => println!("Error: {}", msg), +```rust +fn takes_two_of_the_same_things(x: T, y: T) { + // ... } ``` -The `match` enforces that we handle the `Err` case. In addition, because the -answer is wrapped up in an `Ok`, we can't just use the result without doing -the match: - -```{rust,ignore} -let x = inverse(25.0f64); -println!("{}", x + 2.0f64); // error: binary operation `+` cannot be applied - // to type `core::result::Result` -``` - -This function is great, but there's one other problem: it only works for 64 bit -floating point values. What if we wanted to handle 32 bit floating point as -well? We'd have to write this: +We could write a version that takes multiple types: -```{rust} -fn inverse32(x: f32) -> Result { - if x == 0.0f32 { return Err("x cannot be zero!".to_string()); } - - Ok(1.0f32 / x) +```rust +fn takes_two_things(x: T, y: U) { + // ... } ``` -Bummer. What we need is a *generic function*. Luckily, we can write one! -However, it won't _quite_ work yet. Before we get into that, let's talk syntax. -A generic version of `inverse` would look something like this: +Generic functions are most useful with ‘trait bounds’, which we’ll cover in the +[section on traits][traits]. -```{rust,ignore} -fn inverse(x: T) -> Result { - if x == 0.0 { return Err("x cannot be zero!".to_string()); } +[traits]: traits.html - Ok(1.0 / x) -} -``` +## Generic structs -Just like how we had `Option`, we use a similar syntax for `inverse`. -We can then use `T` inside the rest of the signature: `x` has type `T`, and half -of the `Result` has type `T`. However, if we try to compile that example, we'll get -an error: +You can store a generic type in a `struct` as well: -```text -error: binary operation `==` cannot be applied to type `T` ``` +struct Point { + x: T, + y: T, +} -Because `T` can be _any_ type, it may be a type that doesn't implement `==`, -and therefore, the first line would be wrong. What do we do? +let int_origin = Point { x: 0, y: 0 }; +let float_origin = Point { x: 0.0, y: 0.0 }; +``` -To fix this example, we need to learn about another Rust feature: traits. +Similarly to functions, the `` is where we declare the generic parameters, +and we then use `x: T` in the type declaration, too. diff --git a/src/doc/trpl/if-let.md b/src/doc/trpl/if-let.md index 9e010b020c181..7173303e3b152 100644 --- a/src/doc/trpl/if-let.md +++ b/src/doc/trpl/if-let.md @@ -1,3 +1,82 @@ % if let -COMING SOON +`if let` allows you to combine `if` and `let` together to reduce the overhead +of certain kinds of pattern matches. + +For example, let’s say we have some sort of `Option`. We want to call a function +on it if it’s `Some`, but do nothing if it’s `None`. That looks like this: + +```rust +# let option = Some(5); +# fn foo(x: i32) { } +match option { + Some(x) => { foo(x) }, + None => {}, +} +``` + +We don’t have to use `match` here, for example, we could use `if`: + +```rust +# let option = Some(5); +# fn foo(x: i32) { } +if option.is_some() { + let x = option.unwrap(); + foo(x); +} +``` + +Neither of these options is particularly appealing. We can use `if let` to +do the same thing in a nicer way: + +```rust +# let option = Some(5); +# fn foo(x: i32) { } +if let Some(x) = option { + foo(x); +} +``` + +If a [pattern][patterns] matches successfully, it binds any appropriate parts of +the value to the identifiers in the pattern, then evaluates the expression. If +the pattern doesn’t match, nothing happens. + +If you’d rather to do something else when the pattern does not match, you can +use `else`: + +```rust +# let option = Some(5); +# fn foo(x: i32) { } +# fn bar() { } +if let Some(x) = option { + foo(x); +} else { + bar(); +} +``` + +## `while let` + +In a similar fashion, `while let` can be used when you want to conditionally +loop as long as a value matches a certain pattern. It turns code like this: + +```rust +# let option: Option = None; +loop { + match option { + Some(x) => println!("{}", x), + _ => break, + } +} +``` + +Into code like this: + +```rust +# let option: Option = None; +while let Some(x) = option { + println!("{}", x); +} +``` + +[patterns]: patterns.html diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md index 713814d9147a7..1d4452754baa2 100644 --- a/src/doc/trpl/macros.md +++ b/src/doc/trpl/macros.md @@ -653,6 +653,116 @@ macro_rules! bct { Exercise: use macros to reduce duplication in the above definition of the `bct!` macro. +# Common macros + +Here are some common macros you’ll see in Rust code. + +## panic! + +This macro causes the current thread to panic. You can give it a message +to panic with: + +```rust,no_run +panic!("oh no!"); +``` + +## vec! + +The `vec!` macro is used throughout the book, so you’ve probably seen it +already. It creates `Vec`s with ease: + +```rust +let v = vec![1, 2, 3, 4, 5]; +``` + +It also lets you make vectors with repeating values. For example, a hundred +zeroes: + +```rust +let v = vec![0; 100]; +``` + +## assert! and assert_eq! + +These two macros are used in tests. `assert!` takes a boolean, and `assert_eq!` +takes two values and compares them. Truth passes, success `panic!`s. Like +this: + +```rust,no_run +// A-ok! + +assert!(true); +assert_eq!(5, 3 + 2); + +// nope :( + +assert!(5 < 3); +assert_eq!(5, 3); +``` +## try! + +`try!` is used for error handling. It takes something that can return a +`Result`, and gives `T` if it’s a `Ok`, and `return`s with the +`Err(E)` if it’s that. Like this: + +```rust,no_run +use std::fs::File; + +fn foo() -> std::io::Result<()> { + let f = try!(File::create("foo.txt")); + + Ok(()) +} +``` + +This is cleaner than doing this: + +```rust,no_run +use std::fs::File; + +fn foo() -> std::io::Result<()> { + let f = File::create("foo.txt"); + + let f = match f { + Ok(t) => t, + Err(e) => return Err(e), + }; + + Ok(()) +} +``` + +## unreachable! + +This macro is used when you think some code should never execute: + +```rust +if false { + unreachable!(); +} +``` + +Sometimes, the compiler may make you have a different branch that you know +will never, ever run. In these cases, use this macro, so that if you end +up wrong, you’ll get a `panic!` about it. + +```rust +let x: Option = None; + +match x { + Some(_) => unreachable!(), + None => println!("I know x is None!"), +} +``` + +## unimplemented! + +The `unimplemented!` macro can be used when you’re trying to get your functions +to typecheck, and don’t want to worry about writing out the body of the +function. One example of this situation is implementing a trait with multiple +required methods, where you want to tackle one at a time. Define the others +as `unimplemented!` until you’re ready to write them. + # Procedural macros If Rust's macro system can't do what you need, you may want to write a diff --git a/src/doc/trpl/match.md b/src/doc/trpl/match.md index 33d603f326af3..2c0c8ea73c03c 100644 --- a/src/doc/trpl/match.md +++ b/src/doc/trpl/match.md @@ -1,10 +1,8 @@ % Match -Often, a simple `if`/`else` isn’t enough, because you have more than two -possible options. Also, `else` conditions can get incredibly complicated, so -what’s the solution? - -Rust has a keyword, `match`, that allows you to replace complicated `if`/`else` +Often, a simple [`if`][if]/`else` isn’t enough, because you have more than two +possible options. Also, conditions can get quite complex. Rust +has a keyword, `match`, that allows you to replace complicated `if`/`else` groupings with something more powerful. Check it out: ```rust @@ -20,16 +18,18 @@ match x { } ``` -`match` takes an expression and then branches based on its value. Each *arm* of +[if]: if.html + +`match` takes an expression and then branches based on its value. Each ‘arm’ of the branch is of the form `val => expression`. When the value matches, that arm’s expression will be evaluated. It’s called `match` because of the term ‘pattern matching’, which `match` is an implementation of. There’s an [entire section on -patterns][patterns] coming up next, that covers all the options that fit here. +patterns][patterns] that covers all the patterns that are possible here. [patterns]: patterns.html -So what’s the big advantage here? Well, there are a few. First of all, `match` -enforces *exhaustiveness checking*. Do you see that last arm, the one with the +So what’s the big advantage? Well, there are a few. First of all, `match` +enforces ‘exhaustiveness checking’. Do you see that last arm, the one with the underscore (`_`)? If we remove that arm, Rust will give us an error: ```text @@ -37,11 +37,12 @@ error: non-exhaustive patterns: `_` not covered ``` In other words, Rust is trying to tell us we forgot a value. Because `x` is an -integer, Rust knows that it can have a number of different values – for example, -`6`. Without the `_`, however, there is no arm that could match, and so Rust refuses -to compile. `_` acts like a ‘catch-all arm’. If none of the other arms match, -the arm with `_` will, and since we have this catch-all arm, we now have an arm -for every possible value of `x`, and so our program will compile successfully. +integer, Rust knows that it can have a number of different values – for +example, `6`. Without the `_`, however, there is no arm that could match, and +so Rust refuses to compile the code. `_` acts like a ‘catch-all arm’. If none +of the other arms match, the arm with `_` will, and since we have this +catch-all arm, we now have an arm for every possible value of `x`, and so our +program will compile successfully. `match` is also an expression, which means we can use it on the right-hand side of a `let` binding or directly where an expression is used: @@ -59,4 +60,4 @@ let numer = match x { }; ``` -Sometimes, it’s a nice way of converting things. +Sometimes it’s a nice way of converting something from one type to another. diff --git a/src/doc/trpl/method-syntax.md b/src/doc/trpl/method-syntax.md index ae83a930a187c..5853f3d679c5f 100644 --- a/src/doc/trpl/method-syntax.md +++ b/src/doc/trpl/method-syntax.md @@ -3,27 +3,26 @@ Functions are great, but if you want to call a bunch of them on some data, it can be awkward. Consider this code: -```{rust,ignore} +```rust,ignore baz(bar(foo))); ``` -We would read this left-to right, and so we see "baz bar foo." But this isn't the -order that the functions would get called in, that's inside-out: "foo bar baz." -Wouldn't it be nice if we could do this instead? +We would read this left-to right, and so we see ‘baz bar foo’. But this isn’t the +order that the functions would get called in, that’s inside-out: ‘foo bar baz’. +Wouldn’t it be nice if we could do this instead? -```{rust,ignore} +```rust,ignore foo.bar().baz(); ``` Luckily, as you may have guessed with the leading question, you can! Rust provides -the ability to use this *method call syntax* via the `impl` keyword. +the ability to use this ‘method call syntax’ via the `impl` keyword. ## Method calls -Here's how it works: +Here’s how it works: -```{rust} -# #![feature(core)] +```rust struct Circle { x: f64, y: f64, @@ -44,15 +43,23 @@ fn main() { This will print `12.566371`. -We've made a struct that represents a circle. We then write an `impl` block, -and inside it, define a method, `area`. Methods take a special first -parameter, of which there are three variants: `self`, `&self`, and `&mut self`. -You can think of this first parameter as being the `foo` in `foo.bar()`. The three -variants correspond to the three kinds of things `foo` could be: `self` if it's -just a value on the stack, `&self` if it's a reference, and `&mut self` if it's -a mutable reference. We should default to using `&self`, as you should prefer -borrowing over taking ownership, as well as taking immutable references -over mutable ones. Here's an example of all three variants: + + +We’ve made a struct that represents a circle. We then write an `impl` block, +and inside it, define a method, `area`. + +Methods take a special first parameter, of which there are three variants: +`self`, `&self`, and `&mut self`. You can think of this first parameter as +being the `foo` in `foo.bar()`. The three variants correspond to the three +kinds of things `foo` could be: `self` if it’s just a value on the stack, +`&self` if it’s a reference, and `&mut self` if it’s a mutable reference. +Because we took the `&self` parameter to `area`, we can use it just like any +other parameter. Because we know it’s a `Circle`, we can access the `radius` +just like we would with any other struct. + +We should default to using `&self`, as you should prefer borrowing over taking +ownership, as well as taking immutable references over mutable ones. Here’s an +example of all three variants: ```rust struct Circle { @@ -76,20 +83,13 @@ impl Circle { } ``` -Finally, as you may remember, the value of the area of a circle is `π*r²`. -Because we took the `&self` parameter to `area`, we can use it just like any -other parameter. Because we know it's a `Circle`, we can access the `radius` -just like we would with any other struct. An import of π and some -multiplications later, and we have our area. - ## Chaining method calls So, now we know how to call a method, such as `foo.bar()`. But what about our -original example, `foo.bar().baz()`? This is called 'method chaining', and we +original example, `foo.bar().baz()`? This is called ‘method chaining’, and we can do it by returning `self`. ``` -# #![feature(core)] struct Circle { x: f64, y: f64, @@ -124,13 +124,13 @@ fn grow(&self) -> Circle { # Circle } } ``` -We just say we're returning a `Circle`. With this method, we can grow a new +We just say we’re returning a `Circle`. With this method, we can grow a new circle to any arbitrary size. ## Static methods -You can also define methods that do not take a `self` parameter. Here's a -pattern that's very common in Rust code: +You can also define methods that do not take a `self` parameter. Here’s a +pattern that’s very common in Rust code: ``` struct Circle { @@ -154,20 +154,19 @@ fn main() { } ``` -This *static method* builds a new `Circle` for us. Note that static methods +This ‘static method’ builds a new `Circle` for us. Note that static methods are called with the `Struct::method()` syntax, rather than the `ref.method()` syntax. ## Builder Pattern -Let's say that we want our users to be able to create Circles, but we will +Let’s say that we want our users to be able to create Circles, but we will allow them to only set the properties they care about. Otherwise, the `x` -and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn't +and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn’t have method overloading, named arguments, or variable arguments. We employ the builder pattern instead. It looks like this: ``` -# #![feature(core)] struct Circle { x: f64, y: f64, @@ -224,9 +223,9 @@ fn main() { } ``` -What we've done here is make another struct, `CircleBuilder`. We've defined our -builder methods on it. We've also defined our `area()` method on `Circle`. We +What we’ve done here is make another struct, `CircleBuilder`. We’ve defined our +builder methods on it. We’ve also defined our `area()` method on `Circle`. We also made one more method on `CircleBuilder`: `finalize()`. This method creates -our final `Circle` from the builder. Now, we've used the type system to enforce +our final `Circle` from the builder. Now, we’ve used the type system to enforce our concerns: we can use the methods on `CircleBuilder` to constrain making `Circle`s in any way we choose. diff --git a/src/doc/trpl/patterns.md b/src/doc/trpl/patterns.md index c88e3a0f9edf5..97a3dfe8a7640 100644 --- a/src/doc/trpl/patterns.md +++ b/src/doc/trpl/patterns.md @@ -21,6 +21,8 @@ match x { } ``` +This prints `one`. + # Multiple patterns You can match multiple patterns with `|`: @@ -35,6 +37,8 @@ match x { } ``` +This prints `one or two`. + # Ranges You can match a range of values with `...`: @@ -48,7 +52,21 @@ match x { } ``` -Ranges are mostly used with integers and single characters. +This prints `one through five`. + +Ranges are mostly used with integers and `char`s: + +```rust +let x = '💅'; + +match x { + 'a' ... 'j' => println!("early letter"), + 'k' ... 'z' => println!("late letter"), + _ => println!("something else"), +} +``` + +This prints `something else` # Bindings @@ -64,6 +82,8 @@ match x { } ``` +This prints `got a range element 1`. + # Ignoring variants If you’re matching on an enum which has variants, you can use `..` to @@ -83,6 +103,8 @@ match x { } ``` +This prints `Got an int!`. + # Guards You can introduce ‘match guards’ with `if`: @@ -102,6 +124,8 @@ match x { } ``` +This prints `Got an int!` + # ref and ref mut If you want to get a [reference][ref], use the `ref` keyword: @@ -114,6 +138,8 @@ match x { } ``` +This prints `Got a reference to 5`. + [ref]: references-and-borrowing.html Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref` @@ -130,7 +156,7 @@ match x { # Destructuring -If you have a compound data type, like a `struct`, you can destructure it +If you have a compound data type, like a [`struct`][struct], you can destructure it inside of a pattern: ```rust @@ -146,6 +172,8 @@ match origin { } ``` +[struct]: structs.html + If we only care about some of the values, we don’t have to give them all names: ```rust @@ -161,6 +189,8 @@ match origin { } ``` +This prints `x is 0`. + You can do this kind of match on any member, not just the first: ```rust @@ -176,6 +206,8 @@ match origin { } ``` +This prints `y is 0`. + This ‘destructuring’ behavior works on any compound data type, like [tuples][tuples] or [enums][enums]. @@ -187,10 +219,10 @@ This ‘destructuring’ behavior works on any compound data type, like Whew! That’s a lot of different ways to match things, and they can all be mixed and matched, depending on what you’re doing: -```{rust,ignore} +```rust,ignore match x { Foo { x: Some(ref name), y: None } => ... } ``` -Patterns are very powerful. Make good use of them. +Patterns are very powerful. Make good use of them. diff --git a/src/doc/trpl/raw-pointers.md b/src/doc/trpl/raw-pointers.md new file mode 100644 index 0000000000000..ab6ff18501ed5 --- /dev/null +++ b/src/doc/trpl/raw-pointers.md @@ -0,0 +1,122 @@ +% Raw Pointers + +Rust has a number of different smart pointer types in its standard library, but +there are two types that are extra-special. Much of Rust’s safety comes from +compile-time checks, but raw pointers don’t have such guarantees, and are +[unsafe][unsafe] to use. + +`*const T` and `*mut T` are called ‘raw pointers’ in Rust. Sometimes, when +writing certain kinds of libraries, you’ll need to get around Rust’s safety +guarantees for some reason. In this case, you can use raw pointers to implement +your library, while exposing a safe interface for your users. For example, `*` +pointers are allowed to alias, allowing them to be used to write +shared-ownership types, and even thread-safe shared memory types (the `Rc` +and `Arc` types are both implemented entirely in Rust). + +Here are some things to remember about raw pointers that are different than +other pointer types. They: + +- are not guaranteed to point to valid memory and are not even + guaranteed to be non-null (unlike both `Box` and `&`); +- do not have any automatic clean-up, unlike `Box`, and so require + manual resource management; +- are plain-old-data, that is, they don't move ownership, again unlike + `Box`, hence the Rust compiler cannot protect against bugs like + use-after-free; +- lack any form of lifetimes, unlike `&`, and so the compiler cannot + reason about dangling pointers; and +- have no guarantees about aliasing or mutability other than mutation + not being allowed directly through a `*const T`. + +# Basics + +Creating a raw pointer is perfectly safe: + +```rust +let x = 5; +let raw = &x as *const i32; + +let mut y = 10; +let raw_mut = &mut y as *mut i32; +``` + +However, dereferencing one is not. This won’t work: + +```rust,ignore +let x = 5; +let raw = &x as *const i32; + +println!("raw points at {}", *raw); +``` + +It gives this error: + +```text +error: dereference of unsafe pointer requires unsafe function or block [E0133] + println!("raw points at{}", *raw); + ^~~~ +``` + +When you dereference a raw pointer, you’re taking responsibility that it’s not +pointing somewhere that would be incorrect. As such, you need `unsafe`: + +```rust +let x = 5; +let raw = &x as *const i32; + +let points_at = unsafe { *raw }; + +println!("raw points at {}", points_at); +``` + +For more operations on raw pointers, see [their API documentation][rawapi]. + +[unsafe]: unsafe.html +[rawapi]: ../std/primitive.pointer.html + +# FFI + +Raw pointers are useful for FFI: Rust’s `*const T` and `*mut T` are similar to +C’s `const T*` and `T*`, respectfully. For more about this use, consult the +[FFI chapter][ffi]. + +[ffi]: ffi.md + +# References and raw pointers + +At runtime, a raw pointer `*` and a reference pointing to the same piece of +data have an identical representation. In fact, an `&T` reference will +implicitly coerce to an `*const T` raw pointer in safe code and similarly for +the `mut` variants (both coercions can be performed explicitly with, +respectively, `value as *const T` and `value as *mut T`). + +Going the opposite direction, from `*const` to a reference `&`, is not safe. A +`&T` is always valid, and so, at a minimum, the raw pointer `*const T` has to +point to a valid instance of type `T`. Furthermore, the resulting pointer must +satisfy the aliasing and mutability laws of references. The compiler assumes +these properties are true for any references, no matter how they are created, +and so any conversion from raw pointers is asserting that they hold. The +programmer *must* guarantee this. + +The recommended method for the conversion is + +```rust +let i: u32 = 1; + +// explicit cast +let p_imm: *const u32 = &i as *const u32; +let mut m: u32 = 2; + +// implicit coercion +let p_mut: *mut u32 = &mut m; + +unsafe { + let ref_imm: &u32 = &*p_imm; + let ref_mut: &mut u32 = &mut *p_mut; +} +``` + +The `&*x` dereferencing style is preferred to using a `transmute`. The latter +is far more powerful than necessary, and the more restricted operation is +harder to use incorrectly; for example, it requires that `x` is a pointer +(unlike `transmute`). diff --git a/src/doc/trpl/slice-patterns.md b/src/doc/trpl/slice-patterns.md index 4599333a77a05..de165b70fc402 100644 --- a/src/doc/trpl/slice-patterns.md +++ b/src/doc/trpl/slice-patterns.md @@ -16,3 +16,27 @@ fn main() { } ``` +The `advanced_slice_patterns` gate lets you use `..` to indicate any number of +elements inside a pattern matching a slice. This wildcard can only be used once +for a given array. If there's an identifier before the `..`, the result of the +slice will be bound to that name. For example: + +```rust +#![feature(advanced_slice_patterns, slice_patterns)] + +fn is_symmetric(list: &[u32]) -> bool { + match list { + [] | [_] => true, + [x, inside.., y] if x == y => is_symmetric(inside), + _ => false + } +} + +fn main() { + let sym = &[0, 1, 4, 2, 4, 1, 0]; + assert!(is_symmetric(sym)); + + let not_sym = &[0, 1, 7, 2, 4, 1, 0]; + assert!(!is_symmetric(not_sym)); +} +``` diff --git a/src/doc/trpl/strings.md b/src/doc/trpl/strings.md index 2c2e6a8c7c5ac..6ed4c7cb1b379 100644 --- a/src/doc/trpl/strings.md +++ b/src/doc/trpl/strings.md @@ -1,36 +1,34 @@ % Strings -Strings are an important concept for any programmer to master. Rust's string +Strings are an important concept for any programmer to master. Rust’s string handling system is a bit different from other languages, due to its systems focus. Any time you have a data structure of variable size, things can get -tricky, and strings are a re-sizable data structure. That being said, Rust's +tricky, and strings are a re-sizable data structure. That being said, Rust’s strings also work differently than in some other systems languages, such as C. -Let's dig into the details. A *string* is a sequence of Unicode scalar values -encoded as a stream of UTF-8 bytes. All strings are guaranteed to be -validly encoded UTF-8 sequences. Additionally, strings are not null-terminated -and can contain null bytes. +Let’s dig into the details. A ‘string’ is a sequence of Unicode scalar values +encoded as a stream of UTF-8 bytes. All strings are guaranteed to be a valid +encoding of UTF-8 sequences. Additionally, unlike some systems languages, +strings are not null-terminated and can contain null bytes. -Rust has two main types of strings: `&str` and `String`. +Rust has two main types of strings: `&str` and `String`. Let’s talk about +`&str` first. These are called ‘string slices’. String literals are of the type +`&'static str`: -The first kind is a `&str`. These are called *string slices*. String literals -are of the type `&str`: - -```{rust} -let string = "Hello there."; // string: &str +```rust +let string = "Hello there."; // string: &'static str ``` -This string is statically allocated, meaning that it's saved inside our +This string is statically allocated, meaning that it’s saved inside our compiled program, and exists for the entire duration it runs. The `string` binding is a reference to this statically allocated string. String slices have a fixed size, and cannot be mutated. -A `String`, on the other hand, is a heap-allocated string. This string -is growable, and is also guaranteed to be UTF-8. `String`s are -commonly created by converting from a string slice using the -`to_string` method. +A `String`, on the other hand, is a heap-allocated string. This string is +growable, and is also guaranteed to be UTF-8. `String`s are commonly created by +converting from a string slice using the `to_string` method. -```{rust} +```rust let mut s = "Hello".to_string(); // mut s: String println!("{}", s); @@ -54,8 +52,78 @@ fn main() { Viewing a `String` as a `&str` is cheap, but converting the `&str` to a `String` involves allocating memory. No reason to do that unless you have to! -That's the basics of strings in Rust! They're probably a bit more complicated -than you are used to, if you come from a scripting language, but when the -low-level details matter, they really matter. Just remember that `String`s -allocate memory and control their data, while `&str`s are a reference to -another string, and you'll be all set. +## Indexing + +Because strings are valid UTF-8, strings do not support indexing: + +```rust,ignore +let s = "hello"; + +println!("The first letter of s is {}", s[0]); // ERROR!!! +``` + +Usually, access to a vector with `[]` is very fast. But, because each character +in a UTF-8 encoded string can be multiple bytes, you have to walk over the +string to find the nᵗʰ letter of a string. This is a significantly more +expensive operation, and we don’t want to be misleading. Furthermore, ‘letter’ +isn’t something defined in Unicode, exactly. We can choose to look at a string as +individual bytes, or as codepoints: + +```rust +let hachiko = "忠犬ハチ公"; + +for b in hachiko.as_bytes() { +print!("{}, ", b); +} + +println!(""); + +for c in hachiko.chars() { +print!("{}, ", c); +} + +println!(""); +``` + +This prints: + +```text +229, 191, 160, 231, 138, 172, 227, 131, 143, 227, 131, 129, 229, 133, 172, +忠, 犬, ハ, チ, 公, +``` + +As you can see, there are more bytes than `char`s. + +You can get something similar to an index like this: + +```rust +# let hachiko = "忠犬ハチ公"; +let dog = hachiko.chars().nth(1); // kinda like hachiko[1] +``` + +This emphasizes that we have to go through the whole list of `chars`. + +## Concatenation + +If you have a `String`, you can concatenate a `&str` to the end of it: + +```rust +let hello = "Hello ".to_string(); +let world = "world!"; + +let hello_world = hello + world; +``` + +But if you have two `String`s, you need an `&`: + +```rust +let hello = "Hello ".to_string(); +let world = "world!".to_string(); + +let hello_world = hello + &world; +``` + +This is because `&String` can automatically coerece to a `&str`. This is a +feature called ‘[`Deref` coercions][dc]’. + +[dc]: deref-coercions.html diff --git a/src/doc/trpl/structs.md b/src/doc/trpl/structs.md index 83d5a15bc2c0a..ff249d6043c10 100644 --- a/src/doc/trpl/structs.md +++ b/src/doc/trpl/structs.md @@ -1,6 +1,6 @@ % Structs -Structs are a way of creating more complex datatypes. For example, if we were +Structs are a way of creating more complex data types. For example, if we were doing calculations involving coordinates in 2D space, we would need both an `x` and a `y` value: @@ -24,12 +24,12 @@ fn main() { } ``` -There’s a lot going on here, so let’s break it down. We declare a struct with -the `struct` keyword, and then with a name. By convention, structs begin with a -capital letter and are also camel cased: `PointInSpace`, not `Point_In_Space`. +There’s a lot going on here, so let’s break it down. We declare a `struct` with +the `struct` keyword, and then with a name. By convention, `struct`s begin with +a capital letter and are camel cased: `PointInSpace`, not `Point_In_Space`. We can create an instance of our struct via `let`, as usual, but we use a `key: -value` style syntax to set each field. The order doesn't need to be the same as +value` style syntax to set each field. The order doesn’t need to be the same as in the original declaration. Finally, because fields have names, we can access the field through dot diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md index 25f5c7cacc771..7330e42ccf689 100644 --- a/src/doc/trpl/traits.md +++ b/src/doc/trpl/traits.md @@ -1,10 +1,9 @@ % Traits -Do you remember the `impl` keyword, used to call a function with method -syntax? +Do you remember the `impl` keyword, used to call a function with [method +syntax][methodsyntax]? -```{rust} -# #![feature(core)] +```rust struct Circle { x: f64, y: f64, @@ -18,11 +17,12 @@ impl Circle { } ``` +[methodsyntax]: method-syntax.html + Traits are similar, except that we define a trait with just the method signature, then implement the trait for that struct. Like this: -```{rust} -# #![feature(core)] +```rust struct Circle { x: f64, y: f64, @@ -41,20 +41,13 @@ impl HasArea for Circle { ``` As you can see, the `trait` block looks very similar to the `impl` block, -but we don't define a body, just a type signature. When we `impl` a trait, +but we don’t define a body, just a type signature. When we `impl` a trait, we use `impl Trait for Item`, rather than just `impl Item`. -So what's the big deal? Remember the error we were getting with our generic -`inverse` function? - -```text -error: binary operation `==` cannot be applied to type `T` -``` - We can use traits to constrain our generics. Consider this function, which does not compile, and gives us a similar error: -```{rust,ignore} +```rust,ignore fn print_area(shape: T) { println!("This shape has an area of {}", shape.area()); } @@ -66,11 +59,11 @@ Rust complains: error: type `T` does not implement any method in scope named `area` ``` -Because `T` can be any type, we can't be sure that it implements the `area` -method. But we can add a *trait constraint* to our generic `T`, ensuring +Because `T` can be any type, we can’t be sure that it implements the `area` +method. But we can add a ‘trait constraint’ to our generic `T`, ensuring that it does: -```{rust} +```rust # trait HasArea { # fn area(&self) -> f64; # } @@ -83,10 +76,9 @@ The syntax `` means `any type that implements the HasArea trait`. Because traits define function type signatures, we can be sure that any type which implements `HasArea` will have an `.area()` method. -Here's an extended example of how this works: +Here’s an extended example of how this works: -```{rust} -# #![feature(core)] +```rust trait HasArea { fn area(&self) -> f64; } @@ -144,10 +136,10 @@ This shape has an area of 3.141593 This shape has an area of 1 ``` -As you can see, `print_area` is now generic, but also ensures that we -have passed in the correct types. If we pass in an incorrect type: +As you can see, `print_area` is now generic, but also ensures that we have +passed in the correct types. If we pass in an incorrect type: -```{rust,ignore} +```rust,ignore print_area(5); ``` @@ -157,11 +149,11 @@ We get a compile-time error: error: failed to find an implementation of trait main::HasArea for int ``` -So far, we've only added trait implementations to structs, but you can -implement a trait for any type. So technically, we _could_ implement -`HasArea` for `i32`: +So far, we’ve only added trait implementations to structs, but you can +implement a trait for any type. So technically, we _could_ implement `HasArea` +for `i32`: -```{rust} +```rust trait HasArea { fn area(&self) -> f64; } @@ -181,102 +173,57 @@ It is considered poor style to implement methods on such primitive types, even though it is possible. This may seem like the Wild West, but there are two other restrictions around -implementing traits that prevent this from getting out of hand. First, traits -must be `use`d in any scope where you wish to use the trait's method. So for -example, this does not work: +implementing traits that prevent this from getting out of hand. The first is +that if the trait isn’t defined in your scope, it doesn’t apply. Here’s an +example: the standard library provides a [`Write`][write] trait which adds +extra functionality to `File`s, for doing file I/O. By default, a `File` +won’t have its methods: -```{rust,ignore} -mod shapes { - use std::f64::consts; +[write]: ../std/io/trait.Write.html - trait HasArea { - fn area(&self) -> f64; - } - - struct Circle { - x: f64, - y: f64, - radius: f64, - } - - impl HasArea for Circle { - fn area(&self) -> f64 { - consts::PI * (self.radius * self.radius) - } - } -} - -fn main() { - let c = shapes::Circle { - x: 0.0f64, - y: 0.0f64, - radius: 1.0f64, - }; - - println!("{}", c.area()); -} +```rust,ignore +let mut f = std::fs::File::open("foo.txt").ok().expect("Couldn’t open foo.txt"); +let result = f.write("whatever".as_bytes()); +# result.unwrap(); // ignore the erorr ``` -Now that we've moved the structs and traits into their own module, we get an -error: +Here’s the error: ```text -error: type `shapes::Circle` does not implement any method in scope named `area` -``` +error: type `std::fs::File` does not implement any method in scope named `write` -If we add a `use` line right above `main` and make the right things public, -everything is fine: - -```{rust} -# #![feature(core)] -mod shapes { - use std::f64::consts; - - pub trait HasArea { - fn area(&self) -> f64; - } - - pub struct Circle { - pub x: f64, - pub y: f64, - pub radius: f64, - } - - impl HasArea for Circle { - fn area(&self) -> f64 { - consts::PI * (self.radius * self.radius) - } - } -} +let result = f.write(b”whatever”); + ^~~~~~~~~~~~~~~~~~ +``` -use shapes::HasArea; +We need to `use` the `Write` trait first: -fn main() { - let c = shapes::Circle { - x: 0.0f64, - y: 0.0f64, - radius: 1.0f64, - }; +```rust,ignore +use std::io::Write; - println!("{}", c.area()); -} +let mut f = std::fs::File::open("foo.txt").ok().expect("Couldn’t open foo.txt"); +let result = f.write("whatever".as_bytes()); +# result.unwrap(); // ignore the erorr ``` +This will compile without error. + This means that even if someone does something bad like add methods to `int`, -it won't affect you, unless you `use` that trait. +it won’t affect you, unless you `use` that trait. -There's one more restriction on implementing traits. Either the trait or the -type you're writing the `impl` for must be inside your crate. So, we could -implement the `HasArea` type for `i32`, because `HasArea` is in our crate. But +There’s one more restriction on implementing traits. Either the trait or the +type you’re writing the `impl` for must be defined by you. So, we could +implement the `HasArea` type for `i32`, because `HasArea` is in our code. But if we tried to implement `Float`, a trait provided by Rust, for `i32`, we could -not, because both the trait and the type aren't in our crate. +not, because neither the trait nor the type are in our code. One last thing about traits: generic functions with a trait bound use -*monomorphization* (*mono*: one, *morph*: form), so they are statically -dispatched. What's that mean? Check out the chapter on [trait -objects](trait-objects.html) for more. +‘monomorphization’ (mono: one, morph: form), so they are statically dispatched. +What’s that mean? Check out the chapter on [trait objects][to] for more details. + +[to]: trait-objects.html -## Multiple trait bounds +# Multiple trait bounds You’ve seen that you can bound a generic type parameter with a trait: @@ -299,10 +246,10 @@ fn foo(x: T) { `T` now needs to be both `Clone` as well as `Debug`. -## Where clause +# Where clause Writing functions with only a few generic types and a small number of trait -bounds isn't too bad, but as the number increases, the syntax gets increasingly +bounds isn’t too bad, but as the number increases, the syntax gets increasingly awkward: ``` @@ -318,7 +265,7 @@ fn foo(x: T, y: K) { The name of the function is on the far left, and the parameter list is on the far right. The bounds are getting in the way. -Rust has a solution, and it's called a '`where` clause': +Rust has a solution, and it’s called a ‘`where` clause’: ``` use std::fmt::Debug; @@ -389,84 +336,9 @@ This shows off the additional feature of `where` clauses: they allow bounds where the left-hand side is an arbitrary type (`i32` in this case), not just a plain type parameter (like `T`). -## Our `inverse` Example - -Back in [Generics](generics.html), we were trying to write code like this: - -```{rust,ignore} -fn inverse(x: T) -> Result { - if x == 0.0 { return Err("x cannot be zero!".to_string()); } - - Ok(1.0 / x) -} -``` - -If we try to compile it, we get this error: - -```text -error: binary operation `==` cannot be applied to type `T` -``` - -This is because `T` is too generic: we don't know if a random `T` can be -compared. For that, we can use trait bounds. It doesn't quite work, but try -this: - -```{rust,ignore} -fn inverse(x: T) -> Result { - if x == 0.0 { return Err("x cannot be zero!".to_string()); } - - Ok(1.0 / x) -} -``` - -You should get this error: - -```text -error: mismatched types: - expected `T`, - found `_` -(expected type parameter, - found floating-point variable) -``` - -So this won't work. While our `T` is `PartialEq`, we expected to have another `T`, -but instead, we found a floating-point variable. We need a different bound. `Float` -to the rescue: - -``` -# #![feature(std_misc)] -use std::num::Float; - -fn inverse(x: T) -> Result { - if x == Float::zero() { return Err("x cannot be zero!".to_string()) } - - let one: T = Float::one(); - Ok(one / x) -} -``` - -We've had to replace our generic `0.0` and `1.0` with the appropriate methods -from the `Float` trait. Both `f32` and `f64` implement `Float`, so our function -works just fine: - -``` -# #![feature(std_misc)] -# use std::num::Float; -# fn inverse(x: T) -> Result { -# if x == Float::zero() { return Err("x cannot be zero!".to_string()) } -# let one: T = Float::one(); -# Ok(one / x) -# } -println!("the inverse of {} is {:?}", 2.0f32, inverse(2.0f32)); -println!("the inverse of {} is {:?}", 2.0f64, inverse(2.0f64)); - -println!("the inverse of {} is {:?}", 0.0f32, inverse(0.0f32)); -println!("the inverse of {} is {:?}", 0.0f64, inverse(0.0f64)); -``` - -## Default methods +# Default methods -There's one last feature of traits we should cover: default methods. It's +There’s one last feature of traits we should cover: default methods. It’s easiest just to show an example: ```rust @@ -477,8 +349,8 @@ trait Foo { } ``` -Implementors of the `Foo` trait need to implement `bar()`, but they don't -need to implement `baz()`. They'll get this default behavior. They can +Implementors of the `Foo` trait need to implement `bar()`, but they don’t +need to implement `baz()`. They’ll get this default behavior. They can override the default if they so choose: ```rust @@ -506,3 +378,43 @@ default.baz(); // prints "We called baz." let over = OverrideDefault; over.baz(); // prints "Override baz!" ``` + +# Inheritance + +Sometimes, implementing a trait requires implementing another trait: + +```rust +trait Foo { + fn foo(&self); +} + +trait FooBar : Foo { + fn foobar(&self); +} +``` + +Implementors of `FooBar` must also implement `Foo`, like this: + +```rust +# trait Foo { +# fn foo(&self); +# } +# trait FooBar : Foo { +# fn foobar(&self); +# } +struct Baz; + +impl Foo for Baz { + fn foo(&self) { println!("foo"); } +} + +impl FooBar for Baz { + fn foobar(&self) { println!("foobar"); } +} +``` + +If we forget to implement `Foo`, Rust will tell us: + +```text +error: the trait `main::Foo` is not implemented for the type `main::Baz` [E0277] +``` diff --git a/src/doc/trpl/unsafe-code.md b/src/doc/trpl/unsafe-code.md index b641f2b104a72..ab5e8ed16ad23 100644 --- a/src/doc/trpl/unsafe-code.md +++ b/src/doc/trpl/unsafe-code.md @@ -1,183 +1,128 @@ % Unsafe Code -# Introduction - -Rust aims to provide safe abstractions over the low-level details of -the CPU and operating system, but sometimes one needs to drop down and -write code at that level. This guide aims to provide an overview of -the dangers and power one gets with Rust's unsafe subset. - -Rust provides an escape hatch in the form of the `unsafe { ... }` -block which allows the programmer to dodge some of the compiler's -checks and do a wide range of operations, such as: - -- dereferencing [raw pointers](#raw-pointers) -- calling a function via FFI ([covered by the FFI guide](ffi.html)) -- casting between types bitwise (`transmute`, aka "reinterpret cast") -- [inline assembly](#inline-assembly) - -Note that an `unsafe` block does not relax the rules about lifetimes -of `&` and the freezing of borrowed data. - -Any use of `unsafe` is the programmer saying "I know more than you" to -the compiler, and, as such, the programmer should be very sure that -they actually do know more about why that piece of code is valid. In -general, one should try to minimize the amount of unsafe code in a -code base; preferably by using the bare minimum `unsafe` blocks to -build safe interfaces. - -> **Note**: the low-level details of the Rust language are still in -> flux, and there is no guarantee of stability or backwards -> compatibility. In particular, there may be changes that do not cause -> compilation errors, but do cause semantic changes (such as invoking -> undefined behaviour). As such, extreme care is required. - -# Pointers - -## References - -One of Rust's biggest features is memory safety. This is achieved in -part via [the ownership system](ownership.html), which is how the -compiler can guarantee that every `&` reference is always valid, and, -for example, never pointing to freed memory. - -These restrictions on `&` have huge advantages. However, they also -constrain how we can use them. For example, `&` doesn't behave -identically to C's pointers, and so cannot be used for pointers in -foreign function interfaces (FFI). Additionally, both immutable (`&`) -and mutable (`&mut`) references have some aliasing and freezing -guarantees, required for memory safety. - -In particular, if you have an `&T` reference, then the `T` must not be -modified through that reference or any other reference. There are some -standard library types, e.g. `Cell` and `RefCell`, that provide inner -mutability by replacing compile time guarantees with dynamic checks at -runtime. - -An `&mut` reference has a different constraint: when an object has an -`&mut T` pointing into it, then that `&mut` reference must be the only -such usable path to that object in the whole program. That is, an -`&mut` cannot alias with any other references. - -Using `unsafe` code to incorrectly circumvent and violate these -restrictions is undefined behaviour. For example, the following -creates two aliasing `&mut` pointers, and is invalid. - -``` -use std::mem; -let mut x: u8 = 1; - -let ref_1: &mut u8 = &mut x; -let ref_2: &mut u8 = unsafe { mem::transmute(&mut *ref_1) }; - -// oops, ref_1 and ref_2 point to the same piece of data (x) and are -// both usable -*ref_1 = 10; -*ref_2 = 20; +Rust’s main draw is its powerful static guarantees about behavior. But safety +checks are conservative by nature: there are some programs that are actually +safe, but the compiler is not able to verify this is true. To write these kinds +of programs, we need to tell the compiler to relax its restrictions a bit. For +this, Rust has a keyword, `unsafe`. Code using `unsafe` has less restrictions +than normal code does. + +Let’s go over the syntax, and then we’ll talk semantics. `unsafe` is used in +two contexts. The first one is to mark a function as unsafe: + +```rust +unsafe fn danger_will_robinson() { + // scary stuff +} ``` -## Raw pointers - -Rust offers two additional pointer types (*raw pointers*), written as -`*const T` and `*mut T`. They're an approximation of C's `const T*` and `T*` -respectively; indeed, one of their most common uses is for FFI, -interfacing with external C libraries. - -Raw pointers have much fewer guarantees than other pointer types -offered by the Rust language and libraries. For example, they - -- are not guaranteed to point to valid memory and are not even - guaranteed to be non-null (unlike both `Box` and `&`); -- do not have any automatic clean-up, unlike `Box`, and so require - manual resource management; -- are plain-old-data, that is, they don't move ownership, again unlike - `Box`, hence the Rust compiler cannot protect against bugs like - use-after-free; -- lack any form of lifetimes, unlike `&`, and so the compiler cannot - reason about dangling pointers; and -- have no guarantees about aliasing or mutability other than mutation - not being allowed directly through a `*const T`. - -Fortunately, they come with a redeeming feature: the weaker guarantees -mean weaker restrictions. The missing restrictions make raw pointers -appropriate as a building block for implementing things like smart -pointers and vectors inside libraries. For example, `*` pointers are -allowed to alias, allowing them to be used to write shared-ownership -types like reference counted and garbage collected pointers, and even -thread-safe shared memory types (`Rc` and the `Arc` types are both -implemented entirely in Rust). - -There are two things that you are required to be careful about -(i.e. require an `unsafe { ... }` block) with raw pointers: - -- dereferencing: they can have any value: so possible results include - a crash, a read of uninitialised memory, a use-after-free, or - reading data as normal. -- pointer arithmetic via the `offset` [intrinsic](#intrinsics) (or - `.offset` method): this intrinsic uses so-called "in-bounds" - arithmetic, that is, it is only defined behaviour if the result is - inside (or one-byte-past-the-end) of the object from which the - original pointer came. - -The latter assumption allows the compiler to optimize more -effectively. As can be seen, actually *creating* a raw pointer is not -unsafe, and neither is converting to an integer. - -### References and raw pointers - -At runtime, a raw pointer `*` and a reference pointing to the same -piece of data have an identical representation. In fact, an `&T` -reference will implicitly coerce to an `*const T` raw pointer in safe code -and similarly for the `mut` variants (both coercions can be performed -explicitly with, respectively, `value as *const T` and `value as *mut T`). - -Going the opposite direction, from `*const` to a reference `&`, is not -safe. A `&T` is always valid, and so, at a minimum, the raw pointer -`*const T` has to point to a valid instance of type `T`. Furthermore, -the resulting pointer must satisfy the aliasing and mutability laws of -references. The compiler assumes these properties are true for any -references, no matter how they are created, and so any conversion from -raw pointers is asserting that they hold. The programmer *must* -guarantee this. - -The recommended method for the conversion is +All functions called from [FFI][ffi] must be marked as `unsafe`, for example. +The second use of `unsafe` is an unsafe block: -``` -let i: u32 = 1; -// explicit cast -let p_imm: *const u32 = &i as *const u32; -let mut m: u32 = 2; -// implicit coercion -let p_mut: *mut u32 = &mut m; +[ffi]: ffi.html +```rust unsafe { - let ref_imm: &u32 = &*p_imm; - let ref_mut: &mut u32 = &mut *p_mut; + // scary stuff } ``` -The `&*x` dereferencing style is preferred to using a `transmute`. -The latter is far more powerful than necessary, and the more -restricted operation is harder to use incorrectly; for example, it -requires that `x` is a pointer (unlike `transmute`). +It’s important to be able to explicitly delineate code that may have bugs that +cause big problems. If a Rust program segfaults, you can be sure it’s somewhere +in the sections marked `unsafe`. + +# What does ‘safe’ mean? + +Safe, in the context of Rust, means “doesn’t do anything unsafe.” Easy! + +Okay, let’s try again: what is not safe to do? Here’s a list: + +* Data races +* Dereferencing a null/dangling raw pointer +* Reads of [undef][undef] (uninitialized) memory +* Breaking the [pointer aliasing rules][aliasing] with raw pointers. +* `&mut T` and `&T` follow LLVM’s scoped [noalias][noalias] model, except if + the `&T` contains an `UnsafeCell`. Unsafe code must not violate these + aliasing guarantees. +* Mutating an immutable value/reference without `UnsafeCell` +* Invoking undefined behavior via compiler intrinsics: + * Indexing outside of the bounds of an object with `std::ptr::offset` + (`offset` intrinsic), with + the exception of one byte past the end which is permitted. + * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64` + intrinsics) on overlapping buffers +* Invalid values in primitive types, even in private fields/locals: + * Null/dangling references or boxes + * A value other than `false` (0) or `true` (1) in a `bool` + * A discriminant in an `enum` not included in its type definition + * A value in a `char` which is a surrogate or above `char::MAX` + * Non-UTF-8 byte sequences in a `str` +* Unwinding into Rust from foreign code or unwinding from Rust into foreign + code. + +[noalias]: http://llvm.org/docs/LangRef.html#noalias +[undef]: http://llvm.org/docs/LangRef.html#undefined-values +[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules + +Whew! That’s a bunch of stuff. It’s also important to notice all kinds of +behaviors that are certainly bad, but are expressly _not_ unsafe: + +* Deadlocks +* Reading data from private fields +* Leaks due to reference count cycles +* Exiting without calling destructors +* Sending signals +* Accessing/modifying the file system +* Integer overflow + +Rust cannot prevent all kinds of software problems. Buggy code can and will be +written in Rust. These things arne’t great, but they don’t qualify as `unsafe` +specifically. + +# Unsafe Superpowers + +In both unsafe functions and unsafe blocks, Rust will let you do three things +that you normally can not do. Just three. Here they are: + +1. Access or update a [static mutable variable][static]. +2. Dereference a raw pointer. +3. Call unsafe functions. This is the most powerful ability. + +That’s it. It’s important that `unsafe` does not, for example, ‘turn off the +borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its +semantics, it won’t just start accepting anything. + +But it will let you write things that _do_ break some of the rules. Let’s go +over these three abilities in order. + +## Access or update a `static mut` + +Rust has a feature called ‘`static mut`’ which allows for mutable global state. +Doing so can cause a data race, and as such is inherently not safe. For more +details, see the [static][static] section of the book. + +[static]: static.html + +## Dereference a raw pointer + +Raw pointers let you do arbitrary pointer arithmetic, and can cause a number of +different memory safety and security issues. In some senses, the ability to +dereference an arbitrary pointer is one of the most dangerous things you can +do. For more on raw pointers, see [their section of the book][rawpointers]. + +[rawpointers]: raw-pointers.html +## Call unsafe functions +This last ability works with both aspects of `unsafe`: you can only call +functions marked `unsafe` from inside an unsafe block. -## Making the unsafe safe(r) +This ability is powerful and varied. Rust exposes some [compiler +intrinsics][intrinsics] as unsafe functions, and some unsafe functions bypass +safety checks, trading safety for speed. -There are various ways to expose a safe interface around some unsafe -code: +I’ll repeat again: even though you _can_ do arbitrary things in unsafe blocks +and functions doesn’t mean you should. The compiler will act as though you’re +upholding its invariants, so be careful! -- store pointers privately (i.e. not in public fields of public - structs), so that you can see and control all reads and writes to - the pointer in one place. -- use `assert!()` a lot: since you can't rely on the protection of the - compiler & type-system to ensure that your `unsafe` code is correct - at compile-time, use `assert!()` to verify that it is doing the - right thing at run-time. -- implement the `Drop` for resource clean-up via a destructor, and use - RAII (Resource Acquisition Is Initialization). This reduces the need - for any manual memory management by users, and automatically ensures - that clean-up is always run, even when the thread panics. -- ensure that any data stored behind a raw pointer is destroyed at the - appropriate time. +[intrinsics]: intrinsics.html diff --git a/src/doc/trpl/vectors.md b/src/doc/trpl/vectors.md index 6fa5917ea99ba..965cb218c699a 100644 --- a/src/doc/trpl/vectors.md +++ b/src/doc/trpl/vectors.md @@ -1,37 +1,58 @@ % Vectors -A *vector* is a dynamic or "growable" array, implemented as the standard -library type [`Vec`](../std/vec/) (Where `` is a [Generic](./generics.md) -statement). Vectors always allocate their data on the heap. Vectors are to -[slices][slices] what [`String`][string] is to `&str`. You can -create them with the `vec!` macro: - -```{rust} -let v = vec![1, 2, 3]; // v: Vec -``` +A ‘vector’ is a dynamic or ‘growable’ array, implemented as the standard +library type [`Vec`][vec]. That `` is a [generic][generic], meaning we +can have vectors of any type. Vectors always allocate their data on the heap. +You can create them with the `vec!` macro: -[slices]: primitive-types.html#slices -[string]: strings.html +```rust +let v = vec![1, 2, 3, 4, 5]; // v: Vec +``` -(Notice that unlike the `println!` macro we've used in the past, we use square -brackets `[]` with `vec!`. Rust allows you to use either in either situation, +(Notice that unlike the `println!` macro we’ve used in the past, we use square +brackets `[]` with `vec!` macro. Rust allows you to use either in either situation, this is just convention.) -There's an alternate form of `vec!` for repeating an initial value: +There’s an alternate form of `vec!` for repeating an initial value: ``` let v = vec![0; 10]; // ten zeroes ``` -You can get the length of, iterate over, and subscript vectors just like -arrays. In addition, (mutable) vectors can grow automatically: +## Accessing elements -```{rust} -let mut nums = vec![1, 2, 3]; // mut nums: Vec +To get the value at a particular index in the vector, we use `[]`s: -nums.push(4); +```rust +let v = vec![1, 2, 3, 4, 5]; -println!("The length of nums is now {}", nums.len()); // Prints 4 +println!("The third element of v is {}", v[2]); ``` -Vectors have many more useful methods. +The indices count from `0`, so the third element is `v[2]`. + +## Iterating + +Once you have a vector, you can iterate through its elements with `for`. There +are three versions: + +```rust +let mut v = vec![1, 2, 3, 4, 5]; + +for i in &v { + println!("A reference to {}", i); +} + +for i in &mut v { + println!("A mutable reference to {}", i); +} + +for i in v { + println!("Take ownership of the vector and its element {}", i); +} +``` + +Vectors have many more useful methods, which you can read about in [their +API documentation][vec]. + +[vec]: ../std/vec/index.html diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 0cfdcd2413fd9..3afc34be2cac8 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -103,7 +103,7 @@ use heap::deallocate; /// use std::thread; /// /// fn main() { -/// let numbers: Vec<_> = (0..100u32).map(|i| i as f32).collect(); +/// let numbers: Vec<_> = (0..100u32).collect(); /// let shared_numbers = Arc::new(numbers); /// /// for _ in 0..10 { diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 4468e425a852d..009266c3d2c61 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -10,14 +10,9 @@ //! A pointer type for heap allocation. //! -//! `Box`, casually referred to as a 'box', provides the simplest form of -//! heap allocation in Rust. Boxes provide ownership for this allocation, and -//! drop their contents when they go out of scope. -//! -//! Boxes are useful in two situations: recursive data structures, and -//! occasionally when returning data. [The Pointer chapter of the -//! Book](../../../book/pointers.html#best-practices-1) explains these cases in -//! detail. +//! `Box`, casually referred to as a 'box', provides the simplest form of heap allocation in +//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of +//! scope. //! //! # Examples //! @@ -43,6 +38,16 @@ //! ``` //! //! This will print `Cons(1, Box(Cons(2, Box(Nil))))`. +//! +//! Recursive structures must be boxed, because if the definition of `Cons` looked like this: +//! +//! ```rust,ignore +//! Cons(T, List), +//! ``` +//! +//! It wouldn't work. This is because the size of a `List` depends on how many elements are in the +//! list, and so we don't know how much memory to allocate for a `Cons`. By introducing a `Box`, +//! which has a defined size, we know how big `Cons` needs to be. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 57baa811b9d47..4c7441b1d2a65 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -133,6 +133,7 @@ const MIN_ALIGN: usize = 16; #[cfg(feature = "external_funcs")] mod imp { + #[allow(improper_ctypes)] extern { fn rust_allocate(size: usize, align: usize) -> *mut u8; fn rust_deallocate(ptr: *mut u8, old_size: usize, align: usize); diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index efe1179621de5..dd59ceff577a8 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -14,27 +14,6 @@ //! implement comparison operators. Rust programs may implement `PartialOrd` to overload the `<`, //! `<=`, `>`, and `>=` operators, and may implement `PartialEq` to overload the `==` and `!=` //! operators. -//! -//! For example, to define a type with a customized definition for the PartialEq operators, you -//! could do the following: -//! -//! ``` -//! # #![feature(core)] -//! struct FuzzyNum { -//! num: i32, -//! } -//! -//! impl PartialEq for FuzzyNum { -//! // Our custom eq allows numbers which are near each other to be equal! :D -//! fn eq(&self, other: &FuzzyNum) -> bool { -//! (self.num - other.num).abs() < 5 -//! } -//! } -//! -//! // Now these binary operators will work when applied! -//! assert!(FuzzyNum { num: 37 } == FuzzyNum { num: 34 }); -//! assert!(FuzzyNum { num: 25 } != FuzzyNum { num: 57 }); -//! ``` #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 2d6ef39361e8a..5c862d73537ad 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -341,7 +341,7 @@ impl<'a> DoubleEndedIterator for CharIndices<'a> { /// External iterator for a string's bytes. /// Use with the `std::iter` module. /// -/// Created with `str::bytes` +/// Created with the method `.bytes()`. #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct Bytes<'a>(Map, BytesDeref>); @@ -636,10 +636,10 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { generate_pattern_iterators! { forward: - /// Return type of `str::split()` + /// Created with the method `.split()`. struct Split; reverse: - /// Return type of `str::rsplit()` + /// Created with the method `.rsplit()`. struct RSplit; stability: #[stable(feature = "rust1", since = "1.0.0")] @@ -650,10 +650,10 @@ generate_pattern_iterators! { generate_pattern_iterators! { forward: - /// Return type of `str::split_terminator()` + /// Created with the method `.split_terminator()`. struct SplitTerminator; reverse: - /// Return type of `str::rsplit_terminator()` + /// Created with the method `.rsplit_terminator()`. struct RSplitTerminator; stability: #[stable(feature = "rust1", since = "1.0.0")] @@ -696,10 +696,10 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> { generate_pattern_iterators! { forward: - /// Return type of `str::splitn()` + /// Created with the method `.splitn()`. struct SplitN; reverse: - /// Return type of `str::rsplitn()` + /// Created with the method `.rsplitn()`. struct RSplitN; stability: #[stable(feature = "rust1", since = "1.0.0")] @@ -730,10 +730,10 @@ impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> { generate_pattern_iterators! { forward: - /// Return type of `str::match_indices()` + /// Created with the method `.match_indices()`. struct MatchIndices; reverse: - /// Return type of `str::rmatch_indices()` + /// Created with the method `.rmatch_indices()`. struct RMatchIndices; stability: #[unstable(feature = "core", @@ -771,10 +771,10 @@ impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> { generate_pattern_iterators! { forward: - /// Return type of `str::matches()` + /// Created with the method `.matches()`. struct Matches; reverse: - /// Return type of `str::rmatches()` + /// Created with the method `.rmatches()`. struct RMatches; stability: #[unstable(feature = "core", reason = "type got recently added")] @@ -783,7 +783,7 @@ generate_pattern_iterators! { delegate double ended; } -/// Return type of `str::lines()` +/// Created with the method `.lines()`. #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct Lines<'a>(SplitTerminator<'a, char>); @@ -811,7 +811,7 @@ impl<'a> DoubleEndedIterator for Lines<'a> { } } -/// Return type of `str::lines_any()` +/// Created with the method `.lines_any()`. #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct LinesAny<'a>(Map, LinesAnyMap>); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7f1a4b659edb4..c12ac501c45a2 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -923,6 +923,8 @@ impl NonSnakeCase { allow_underscore = match c { '_' if !allow_underscore => return false, '_' => false, + // It would be more obvious to use `c.is_lowercase()`, + // but some characters do not have a lowercase form c if !c.is_uppercase() => true, _ => return false, };