Merge remote-tracking branch 'origin/master' into 0.11.0-release
Conflicts: src/libstd/lib.rs
This commit is contained in:
commit
ff1dd44b40
715 changed files with 10358 additions and 8207 deletions
|
|
@ -50,19 +50,19 @@ use libc::{c_int, size_t};
|
|||
|
||||
#[link(name = "snappy")]
|
||||
extern {
|
||||
fn snappy_compress(input: *u8,
|
||||
fn snappy_compress(input: *const u8,
|
||||
input_length: size_t,
|
||||
compressed: *mut u8,
|
||||
compressed_length: *mut size_t) -> c_int;
|
||||
fn snappy_uncompress(compressed: *u8,
|
||||
fn snappy_uncompress(compressed: *const u8,
|
||||
compressed_length: size_t,
|
||||
uncompressed: *mut u8,
|
||||
uncompressed_length: *mut size_t) -> c_int;
|
||||
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
|
||||
fn snappy_uncompressed_length(compressed: *u8,
|
||||
fn snappy_uncompressed_length(compressed: *const u8,
|
||||
compressed_length: size_t,
|
||||
result: *mut size_t) -> c_int;
|
||||
fn snappy_validate_compressed_buffer(compressed: *u8,
|
||||
fn snappy_validate_compressed_buffer(compressed: *const u8,
|
||||
compressed_length: size_t) -> c_int;
|
||||
}
|
||||
# fn main() {}
|
||||
|
|
@ -82,7 +82,7 @@ the allocated memory. The length is less than or equal to the capacity.
|
|||
~~~~
|
||||
# extern crate libc;
|
||||
# use libc::{c_int, size_t};
|
||||
# unsafe fn snappy_validate_compressed_buffer(_: *u8, _: size_t) -> c_int { 0 }
|
||||
# unsafe fn snappy_validate_compressed_buffer(_: *const u8, _: size_t) -> c_int { 0 }
|
||||
# fn main() {}
|
||||
pub fn validate_compressed_buffer(src: &[u8]) -> bool {
|
||||
unsafe {
|
||||
|
|
@ -106,7 +106,7 @@ the true length after compression for setting the length.
|
|||
~~~~
|
||||
# extern crate libc;
|
||||
# use libc::{size_t, c_int};
|
||||
# unsafe fn snappy_compress(a: *u8, b: size_t, c: *mut u8,
|
||||
# unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8,
|
||||
# d: *mut size_t) -> c_int { 0 }
|
||||
# unsafe fn snappy_max_compressed_length(a: size_t) -> size_t { a }
|
||||
# fn main() {}
|
||||
|
|
@ -132,11 +132,11 @@ format and `snappy_uncompressed_length` will retrieve the exact buffer size requ
|
|||
~~~~
|
||||
# extern crate libc;
|
||||
# use libc::{size_t, c_int};
|
||||
# unsafe fn snappy_uncompress(compressed: *u8,
|
||||
# unsafe fn snappy_uncompress(compressed: *const u8,
|
||||
# compressed_length: size_t,
|
||||
# uncompressed: *mut u8,
|
||||
# uncompressed_length: *mut size_t) -> c_int { 0 }
|
||||
# unsafe fn snappy_uncompressed_length(compressed: *u8,
|
||||
# unsafe fn snappy_uncompressed_length(compressed: *const u8,
|
||||
# compressed_length: size_t,
|
||||
# result: *mut size_t) -> c_int { 0 }
|
||||
# fn main() {}
|
||||
|
|
@ -418,7 +418,7 @@ Unsafe functions, on the other hand, advertise it to the world. An unsafe functi
|
|||
this:
|
||||
|
||||
~~~~
|
||||
unsafe fn kaboom(ptr: *int) -> int { *ptr }
|
||||
unsafe fn kaboom(ptr: *const int) -> int { *ptr }
|
||||
~~~~
|
||||
|
||||
This function can only be called from an `unsafe` block or another `unsafe` function.
|
||||
|
|
@ -453,7 +453,7 @@ use std::ptr;
|
|||
|
||||
#[link(name = "readline")]
|
||||
extern {
|
||||
static mut rl_prompt: *libc::c_char;
|
||||
static mut rl_prompt: *const libc::c_char;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
@ -478,7 +478,7 @@ extern crate libc;
|
|||
#[link(name = "kernel32")]
|
||||
#[allow(non_snake_case_functions)]
|
||||
extern "stdcall" {
|
||||
fn SetEnvironmentVariableA(n: *u8, v: *u8) -> libc::c_int;
|
||||
fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int;
|
||||
}
|
||||
# fn main() { }
|
||||
~~~~
|
||||
|
|
|
|||
|
|
@ -355,6 +355,7 @@ macro_rules! biased_match_rec (
|
|||
_ => { $err }
|
||||
}
|
||||
);
|
||||
// Produce the requested values
|
||||
( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )
|
||||
)
|
||||
|
||||
|
|
@ -364,7 +365,7 @@ macro_rules! biased_match (
|
|||
( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
|
||||
binds $bind_res:ident
|
||||
) => (
|
||||
let ( $( $bind_res ),* ) = biased_match_rec!(
|
||||
let $bind_res = biased_match_rec!(
|
||||
$( ($e) ~ ($p) else $err ; )*
|
||||
binds $bind_res
|
||||
);
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ extern crate green;
|
|||
extern crate rustuv;
|
||||
|
||||
#[start]
|
||||
fn start(argc: int, argv: **u8) -> int {
|
||||
fn start(argc: int, argv: *const *const u8) -> int {
|
||||
green::start(argc, argv, rustuv::event_loop, main)
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +261,9 @@ inside of an OS thread.
|
|||
extern crate native;
|
||||
|
||||
#[start]
|
||||
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }
|
||||
fn start(argc: int, argv: *const *const u8) -> int {
|
||||
native::start(argc, argv, main)
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -457,6 +457,8 @@ the string in response. The child terminates when it receives `0`.
|
|||
Here is the function that implements the child task:
|
||||
|
||||
~~~
|
||||
#![allow(deprecated)]
|
||||
|
||||
use std::comm::DuplexStream;
|
||||
# fn main() {
|
||||
fn stringifier(channel: &DuplexStream<String, uint>) {
|
||||
|
|
@ -481,6 +483,8 @@ response itself is simply the stringified version of the received value,
|
|||
Here is the code for the parent task:
|
||||
|
||||
~~~
|
||||
#![allow(deprecated)]
|
||||
|
||||
use std::comm::duplex;
|
||||
# use std::task::spawn;
|
||||
# use std::comm::DuplexStream;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ let ref_2: &mut u8 = unsafe { mem::transmute(&mut *ref_1) };
|
|||
## Raw pointers
|
||||
|
||||
Rust offers two additional pointer types "raw pointers", written as
|
||||
`*T` and `*mut T`. They're an approximation of C's `const T*` and `T*`
|
||||
`*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.
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ offered by the Rust language and libraries. For example, they
|
|||
- 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 `*T`.
|
||||
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
|
||||
|
|
@ -131,13 +131,13 @@ unsafe, and neither is converting to an integer.
|
|||
|
||||
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 `*T` raw pointer in safe code
|
||||
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 *T` and `value as *mut T`).
|
||||
explicitly with, respectively, `value as *const T` and `value as *mut T`).
|
||||
|
||||
Going the opposite direction, from `*` to a reference `&`, is not
|
||||
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
|
||||
`*T` has to be a valid to a valid instance of type `T`. Furthermore,
|
||||
`*const T` has to be a valid 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
|
||||
|
|
@ -149,7 +149,7 @@ The recommended method for the conversion is
|
|||
```
|
||||
let i: u32 = 1;
|
||||
// explicit cast
|
||||
let p_imm: *u32 = &i as *u32;
|
||||
let p_imm: *const u32 = &i as *const u32;
|
||||
let mut m: u32 = 2;
|
||||
// implicit coercion
|
||||
let p_mut: *mut u32 = &mut m;
|
||||
|
|
@ -256,7 +256,7 @@ impl<T: Send> Drop for Unique<T> {
|
|||
// Copy the object out from the pointer onto the stack,
|
||||
// where it is covered by normal Rust destructor semantics
|
||||
// and cleans itself up, if necessary
|
||||
ptr::read(self.ptr as *T);
|
||||
ptr::read(self.ptr as *const T);
|
||||
|
||||
// clean-up our allocation
|
||||
free(self.ptr as *mut c_void)
|
||||
|
|
@ -267,12 +267,12 @@ impl<T: Send> Drop for Unique<T> {
|
|||
// A comparison between the built-in `Box` and this reimplementation
|
||||
fn main() {
|
||||
{
|
||||
let mut x = box 5;
|
||||
let mut x = box 5i;
|
||||
*x = 10;
|
||||
} // `x` is freed here
|
||||
|
||||
{
|
||||
let mut y = Unique::new(5);
|
||||
let mut y = Unique::new(5i);
|
||||
*y.borrow_mut() = 10;
|
||||
} // `y` is freed here
|
||||
}
|
||||
|
|
@ -457,7 +457,7 @@ extern crate libc;
|
|||
|
||||
// Entry point for this program
|
||||
#[start]
|
||||
fn start(_argc: int, _argv: **u8) -> int {
|
||||
fn start(_argc: int, _argv: *const *const u8) -> int {
|
||||
0
|
||||
}
|
||||
|
||||
|
|
@ -482,7 +482,7 @@ compiler's name mangling too:
|
|||
extern crate libc;
|
||||
|
||||
#[no_mangle] // ensure that this symbol is called `main` in the output
|
||||
pub extern fn main(argc: int, argv: **u8) -> int {
|
||||
pub extern fn main(argc: int, argv: *const *const u8) -> int {
|
||||
0
|
||||
}
|
||||
|
||||
|
|
@ -540,8 +540,8 @@ use core::mem;
|
|||
use core::raw::Slice;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn dot_product(a: *u32, a_len: u32,
|
||||
b: *u32, b_len: u32) -> u32 {
|
||||
pub extern fn dot_product(a: *const u32, a_len: u32,
|
||||
b: *const u32, b_len: u32) -> u32 {
|
||||
// Convert the provided arrays into Rust slices.
|
||||
// The core::raw module guarantees that the Slice
|
||||
// structure has the same memory layout as a &[T]
|
||||
|
|
@ -573,7 +573,7 @@ extern fn begin_unwind(args: &core::fmt::Arguments,
|
|||
|
||||
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
|
||||
#[lang = "eh_personality"] extern fn eh_personality() {}
|
||||
# #[start] fn start(argc: int, argv: **u8) -> int { 0 }
|
||||
# #[start] fn start(argc: int, argv: *const *const u8) -> int { 0 }
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
|
|
@ -595,7 +595,7 @@ standard library itself.
|
|||
> parts of the language may never be full specified and so details may
|
||||
> differ wildly between implementations (and even versions of `rustc`
|
||||
> itself).
|
||||
>
|
||||
>
|
||||
> Furthermore, this is just an overview; the best form of
|
||||
> documentation for specific instances of these features are their
|
||||
> definitions and uses in `std`.
|
||||
|
|
@ -627,7 +627,7 @@ via a declaration like
|
|||
extern "rust-intrinsic" {
|
||||
fn transmute<T, U>(x: T) -> U;
|
||||
|
||||
fn offset<T>(dst: *T, offset: int) -> *T;
|
||||
fn offset<T>(dst: *const T, offset: int) -> *const T;
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -677,8 +677,8 @@ unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
|
|||
}
|
||||
|
||||
#[start]
|
||||
fn main(argc: int, argv: **u8) -> int {
|
||||
let x = box 1;
|
||||
fn main(argc: int, argv: *const *const u8) -> int {
|
||||
let x = box 1i;
|
||||
|
||||
0
|
||||
}
|
||||
|
|
|
|||
242
src/doc/guide.md
242
src/doc/guide.md
|
|
@ -160,7 +160,7 @@ Save the file, and then type this into your terminal window:
|
|||
|
||||
```{bash}
|
||||
$ rustc hello_world.rs
|
||||
$ ./hello_world # just 'hello_world' on Windows
|
||||
$ ./hello_world # or hello_world.exe on Windows
|
||||
Hello, world
|
||||
```
|
||||
|
||||
|
|
@ -243,7 +243,7 @@ There are now two files: our source code, with the `.rs` extension, and the
|
|||
executable (`hello_world.exe` on Windows, `hello_world` everywhere else)
|
||||
|
||||
```{bash}
|
||||
$ ./hello_world # or ./hello_world.exe on Windows
|
||||
$ ./hello_world # or hello_world.exe on Windows
|
||||
```
|
||||
|
||||
This prints out our `Hello, world!` text to our terminal.
|
||||
|
|
@ -285,8 +285,9 @@ At first, your program doesn't have any dependencies, so we'll only be using
|
|||
the first part of its functionality. Eventually, we'll add more. Since we
|
||||
started off by using Cargo, it'll be easy to add later.
|
||||
|
||||
Let's convert Hello World to Cargo. The first thing we need to do is install
|
||||
it. To do this, we need to build it from source. There are no binaries yet.
|
||||
Let's convert Hello World to Cargo. The first thing we need to do to begin using Cargo
|
||||
is to install Cargo. To do this, we need to build it from source. There are no binaries
|
||||
yet.
|
||||
|
||||
First, let's go back to our projects directory. We don't want Cargo to
|
||||
live in our project!
|
||||
|
|
@ -412,6 +413,202 @@ rest of your Rust career.
|
|||
Next, we'll learn more about Rust itself, by starting to write a more complicated
|
||||
program. We hope you want to do more with Rust than just print "Hello, world!"
|
||||
|
||||
## Guessing Game
|
||||
|
||||
Let's write a bigger program in Rust. We could just go through a laundry list
|
||||
of Rust features, but that's boring. Instead, we'll learn more about how to
|
||||
code in Rust by writing a few example projects.
|
||||
|
||||
For our first project, we'll implement a classic beginner programming problem:
|
||||
the guessing game. Here's how it works: Our program will generate a random
|
||||
integer between one and a hundred. It will then prompt us to enter a guess.
|
||||
Upon entering our guess, it will tell us if we're too low or too high. Once we
|
||||
guess correctly, it will congratulate us, and print the number of guesses we've
|
||||
taken to the screen. Sound good? It sounds easy, but it'll end up showing off a
|
||||
number of basic features of Rust.
|
||||
|
||||
### Set up
|
||||
|
||||
Let's set up a new project. Go to your projects directory, and make a new
|
||||
directory for the project, as well as a `src` directory for our code:
|
||||
|
||||
```{bash}
|
||||
$ cd ~/projects
|
||||
$ mkdir guessing_game
|
||||
$ cd guessing_game
|
||||
$ mkdir src
|
||||
```
|
||||
|
||||
Great. Next, let's make a `Cargo.toml` file so Cargo knows how to build our
|
||||
project:
|
||||
|
||||
```{ignore}
|
||||
[package]
|
||||
|
||||
name = "guessing_game"
|
||||
version = "0.1.0"
|
||||
authors = [ "someone@example.com" ]
|
||||
|
||||
[[bin]]
|
||||
|
||||
name = "guessing_game"
|
||||
```
|
||||
|
||||
Finally, we need our source file. Let's just make it hello world for now, so we
|
||||
can check that our setup works. In `src/guessing_game.rs`:
|
||||
|
||||
```{rust}
|
||||
fn main() {
|
||||
println!("Hello world!");
|
||||
}
|
||||
```
|
||||
|
||||
Let's make sure that worked:
|
||||
|
||||
```{bash}
|
||||
$ cargo build
|
||||
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
|
||||
$
|
||||
```
|
||||
|
||||
Excellent! Open up your `src/guessing_game.rs` again. We'll be writing all of
|
||||
our code in this file. The next section of the tutorial will show you how to
|
||||
build multiple-file projects.
|
||||
|
||||
## Variable bindings
|
||||
|
||||
The first thing we'll learn about are 'variable bindings.' They look like this:
|
||||
|
||||
```{rust}
|
||||
let x = 5i;
|
||||
```
|
||||
|
||||
In many languages, this is called a 'variable.' But Rust's variable bindings
|
||||
have a few tricks up their sleeves. Rust has a very powerful feature called
|
||||
'pattern matching' that we'll get into detail with later, but the left
|
||||
hand side of a `let` expression is a full pattern, not just a variable name.
|
||||
This means we can do things like:
|
||||
|
||||
```{rust}
|
||||
let (x, y) = (1i, 2i);
|
||||
```
|
||||
|
||||
After this expression is evaluated, `x` will be one, and `y` will be two.
|
||||
Patterns are really powerful, but this is about all we can do with them so far.
|
||||
So let's just keep this in the back of our minds as we go forward.
|
||||
|
||||
By the way, in these examples, `i` indicates that the number is an integer.
|
||||
|
||||
Rust is a statically typed language, which means that we specify our types up
|
||||
front. So why does our first example compile? Well, Rust has this thing called
|
||||
"[Hindley-Milner type
|
||||
inference](http://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)",
|
||||
named after some really smart type theorists. If you clicked that link, don't
|
||||
be scared: what this means for you is that Rust will attempt to infer the types
|
||||
in your program, and it's pretty good at it. If it can infer the type, Rust
|
||||
doesn't require you to actually type it out.
|
||||
|
||||
We can add the type if we want to. Types come after a colon (`:`):
|
||||
|
||||
```{rust}
|
||||
let x: int = 5;
|
||||
```
|
||||
|
||||
If I asked you to read this out loud to the rest of the class, you'd say "`x`
|
||||
is a binding with the type `int` and the value `five`." Rust requires you to
|
||||
initialize the binding with a value before you're allowed to use it. If
|
||||
we try...
|
||||
|
||||
```{ignore}
|
||||
let x;
|
||||
```
|
||||
|
||||
...we'll get an error:
|
||||
|
||||
```{ignore}
|
||||
src/guessing_game.rs:2:9: 2:10 error: cannot determine a type for this local variable: unconstrained type
|
||||
src/guessing_game.rs:2 let x;
|
||||
^
|
||||
```
|
||||
|
||||
Giving it a type will compile, though:
|
||||
|
||||
```{ignore}
|
||||
let x: int;
|
||||
```
|
||||
|
||||
Let's try it out. Change your `src/guessing_game.rs` file to look like this:
|
||||
|
||||
```{rust}
|
||||
fn main() {
|
||||
let x: int;
|
||||
|
||||
println!("Hello world!");
|
||||
}
|
||||
```
|
||||
|
||||
You can use `cargo build` on the command line to build it. You'll get a warning,
|
||||
but it will still print "Hello, world!":
|
||||
|
||||
```{ignore,notrust}
|
||||
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
|
||||
src/guessing_game.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default
|
||||
src/guessing_game.rs:2 let x: int;
|
||||
^
|
||||
```
|
||||
|
||||
Rust warns us that we never use the variable binding, but since we never use it,
|
||||
no harm, no foul. Things change if we try to actually use this `x`, however. Let's
|
||||
do that. Change your program to look like this:
|
||||
|
||||
```{rust,ignore}
|
||||
fn main() {
|
||||
let x: int;
|
||||
|
||||
println!("The value of x is: {}", x);
|
||||
}
|
||||
```
|
||||
|
||||
And try to build it. You'll get an error:
|
||||
|
||||
```{bash}
|
||||
$ cargo build
|
||||
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
|
||||
src/guessing_game.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x`
|
||||
src/guessing_game.rs:4 println!("The value of x is: {}", x);
|
||||
^
|
||||
note: in expansion of format_args!
|
||||
<std macros>:2:23: 2:77 note: expansion site
|
||||
<std macros>:1:1: 3:2 note: in expansion of println!
|
||||
src/guessing_game.rs:4:5: 4:42 note: expansion site
|
||||
error: aborting due to previous error
|
||||
Could not execute process `rustc src/guessing_game.rs --crate-type bin --out-dir /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target/deps` (status=101)
|
||||
```
|
||||
|
||||
Rust will not let us use a value that has not been initialized. So why let us
|
||||
declare a binding without initializing it? You'd think our first example would
|
||||
have errored. Well, Rust is smarter than that. Before we get to that, let's talk
|
||||
about this stuff we've added to `println!`.
|
||||
|
||||
If you include two curly braces (`{}`, some call them moustaches...) in your
|
||||
string to print, Rust will interpret this as a request to interpolate some sort
|
||||
of value. **String interpolation** is a computer science term that means "stick
|
||||
in the middle of a string." We add a comma, and then `x`, to indicate that we
|
||||
want `x` to be the value we're interpolating. The comma is used to separate
|
||||
arguments we pass to functions and macros, if you're passing more than one.
|
||||
|
||||
When you just use the double curly braces, Rust will attempt to display the
|
||||
value in a meaningful way by checking out its type. If you want to specify the
|
||||
format in a more detailed manner, there are a [wide number of options
|
||||
available](/std/fmt/index.html). Fow now, we'll just stick to the default:
|
||||
integers aren't very complicated to print.
|
||||
|
||||
So, we've cleared up all of the confusion around bindings, with one exception:
|
||||
why does Rust let us declare a variable binding without an initial value if we
|
||||
must initialize the binding before we use it? And how does it know that we have
|
||||
or have not initialized the binding? For that, we need to learn our next
|
||||
concept: `if`.
|
||||
|
||||
## If
|
||||
|
||||
## Functions
|
||||
|
|
@ -420,16 +617,6 @@ return
|
|||
|
||||
comments
|
||||
|
||||
## Testing
|
||||
|
||||
attributes
|
||||
|
||||
stability markers
|
||||
|
||||
## Crates and Modules
|
||||
|
||||
visibility
|
||||
|
||||
## Compound Data Types
|
||||
|
||||
Tuples
|
||||
|
|
@ -450,10 +637,35 @@ loop
|
|||
|
||||
break/continue
|
||||
|
||||
iterators
|
||||
## Guessing Game: complete
|
||||
|
||||
At this point, you have successfully built the Guessing Game! Congratulations!
|
||||
For reference, [We've placed the sample code on
|
||||
GitHub](https://github.com/steveklabnik/guessing_game).
|
||||
|
||||
You've now learned the basic syntax of Rust. All of this is relatively close to
|
||||
various other programming languages you have used in the past. These
|
||||
fundamental syntactical and semantic elements will form the foundation for the
|
||||
rest of your Rust education.
|
||||
|
||||
Now that you're an expert at the basics, it's time to learn about some of
|
||||
Rust's more unique features.
|
||||
|
||||
## iterators
|
||||
|
||||
## Lambdas
|
||||
|
||||
## Testing
|
||||
|
||||
attributes
|
||||
|
||||
stability markers
|
||||
|
||||
## Crates and Modules
|
||||
|
||||
visibility
|
||||
|
||||
|
||||
## Generics
|
||||
|
||||
## Traits
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ Check it out:
|
|||
```
|
||||
|
||||
fn dangling() -> Box<int> {
|
||||
let i = box 1234;
|
||||
let i = box 1234i;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -143,8 +143,8 @@ fn add_one() -> int {
|
|||
}
|
||||
```
|
||||
|
||||
Now instead of a stack allocated `1234`,
|
||||
we have a heap allocated `box 1234`.
|
||||
Now instead of a stack allocated `1234i`,
|
||||
we have a heap allocated `box 1234i`.
|
||||
Whereas `&` borrows a pointer to existing memory,
|
||||
creating an owned box allocates memory on the heap and places a value in it,
|
||||
giving you the sole pointer to that memory.
|
||||
|
|
@ -152,7 +152,7 @@ You can roughly compare these two lines:
|
|||
|
||||
```
|
||||
// Rust
|
||||
let i = box 1234;
|
||||
let i = box 1234i;
|
||||
```
|
||||
|
||||
```cpp
|
||||
|
|
@ -252,7 +252,7 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
This will result an error indicating that the value is no longer in scope:
|
||||
The compiler will produce an error indicating that the value is no longer in scope:
|
||||
|
||||
```text
|
||||
concurrency.rs:12:20: 12:27 error: use of moved value: 'numbers'
|
||||
|
|
|
|||
|
|
@ -442,17 +442,14 @@ of integer literal suffix:
|
|||
The type of an _unsuffixed_ integer literal is determined by type inference.
|
||||
If an integer type can be _uniquely_ determined from the surrounding program
|
||||
context, the unsuffixed integer literal has that type. If the program context
|
||||
underconstrains the type, the unsuffixed integer literal's type is `int`; if
|
||||
the program context overconstrains the type, it is considered a static type
|
||||
error.
|
||||
underconstrains the type, it is considered a static type error;
|
||||
if the program context overconstrains the type,
|
||||
it is also considered a static type error.
|
||||
|
||||
Examples of integer literals of various forms:
|
||||
|
||||
~~~~
|
||||
123; 0xff00; // type determined by program context
|
||||
// defaults to int in absence of type
|
||||
// information
|
||||
|
||||
123i; // type int
|
||||
123u; // type uint
|
||||
123_u; // type uint
|
||||
0xff_u8; // type u8
|
||||
|
|
@ -469,8 +466,10 @@ A _floating-point literal_ has one of two forms:
|
|||
second decimal literal.
|
||||
* A single _decimal literal_ followed by an _exponent_.
|
||||
|
||||
By default, a floating-point literal has a generic type, but will fall back to
|
||||
`f64`. A floating-point literal may be followed (immediately, without any
|
||||
By default, a floating-point literal has a generic type,
|
||||
and, like integer literals, the type must be uniquely determined
|
||||
from the context.
|
||||
A floating-point literal may be followed (immediately, without any
|
||||
spaces) by a _floating-point suffix_, which changes the type of the literal.
|
||||
There are two floating-point suffixes: `f32`, and `f64` (the 32-bit and 64-bit
|
||||
floating point types).
|
||||
|
|
@ -478,8 +477,8 @@ floating point types).
|
|||
Examples of floating-point literals of various forms:
|
||||
|
||||
~~~~
|
||||
123.0; // type f64
|
||||
0.1; // type f64
|
||||
123.0f64; // type f64
|
||||
0.1f64; // type f64
|
||||
0.1f32; // type f32
|
||||
12E+99_f64; // type f64
|
||||
~~~~
|
||||
|
|
@ -1614,7 +1613,7 @@ extern crate libc;
|
|||
use libc::{c_char, FILE};
|
||||
|
||||
extern {
|
||||
fn fopen(filename: *c_char, mode: *c_char) -> *FILE;
|
||||
fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE;
|
||||
}
|
||||
# fn main() {}
|
||||
~~~~
|
||||
|
|
@ -2700,9 +2699,9 @@ must be a constant expression that can be evaluated at compile time, such
|
|||
as a [literal](#literals) or a [static item](#static-items).
|
||||
|
||||
~~~~
|
||||
[1, 2, 3, 4];
|
||||
[1i, 2, 3, 4];
|
||||
["a", "b", "c", "d"];
|
||||
[0, ..128]; // vector with 128 zeros
|
||||
[0i, ..128]; // vector with 128 zeros
|
||||
[0u8, 0u8, 0u8, 0u8];
|
||||
~~~~
|
||||
|
||||
|
|
@ -2881,7 +2880,7 @@ equals sign (`=`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression.
|
|||
Evaluating an assignment expression [either copies or moves](#moved-and-copied-types) its right-hand operand to its left-hand operand.
|
||||
|
||||
~~~~
|
||||
# let mut x = 0;
|
||||
# let mut x = 0i;
|
||||
# let y = 0;
|
||||
|
||||
x = y;
|
||||
|
|
@ -2932,7 +2931,7 @@ paren_expr : '(' expr ')' ;
|
|||
An example of a parenthesized expression:
|
||||
|
||||
~~~~
|
||||
let x = (2 + 3) * 4;
|
||||
let x: int = (2 + 3) * 4;
|
||||
~~~~
|
||||
|
||||
|
||||
|
|
@ -3016,7 +3015,7 @@ conditional expression evaluates to `false`, the `while` expression completes.
|
|||
An example:
|
||||
|
||||
~~~~
|
||||
let mut i = 0;
|
||||
let mut i = 0u;
|
||||
|
||||
while i < 10 {
|
||||
println!("hello");
|
||||
|
|
@ -3262,7 +3261,7 @@ Patterns can also dereference pointers by using the `&`,
|
|||
on `x: &int` are equivalent:
|
||||
|
||||
~~~~
|
||||
# let x = &3;
|
||||
# let x = &3i;
|
||||
let y = match *x { 0 => "zero", _ => "some" };
|
||||
let z = match x { &0 => "zero", _ => "some" };
|
||||
|
||||
|
|
@ -3285,7 +3284,7 @@ A range of values may be specified with `..`.
|
|||
For example:
|
||||
|
||||
~~~~
|
||||
# let x = 2;
|
||||
# let x = 2i;
|
||||
|
||||
let message = match x {
|
||||
0 | 1 => "not many",
|
||||
|
|
|
|||
|
|
@ -103,6 +103,17 @@ rustdoc can also generate JSON, for consumption by other tools, with
|
|||
`rustdoc --output-format json`, and also consume already-generated JSON with
|
||||
`rustdoc --input-format json`.
|
||||
|
||||
rustdoc also supports personalizing the output from crates' documentation,
|
||||
similar to markdown options.
|
||||
|
||||
- `--html-in-header FILE`: includes the contents of `FILE` at the
|
||||
end of the `<head>...</head>` section.
|
||||
- `--html-before-content FILE`: includes the contents of `FILE`
|
||||
directly after `<body>`, before the rendered content (including the
|
||||
search bar).
|
||||
- `--html-after-content FILE`: includes the contents of `FILE`
|
||||
after all the rendered content.
|
||||
|
||||
# Using the Documentation
|
||||
|
||||
The web pages generated by rustdoc present the same logical hierarchy that one
|
||||
|
|
@ -238,16 +249,16 @@ detected by a `.md` or `.markdown` extension.
|
|||
There are 4 options to modify the output that Rustdoc creates.
|
||||
|
||||
- `--markdown-css PATH`: adds a `<link rel="stylesheet">` tag pointing to `PATH`.
|
||||
- `--markdown-in-header FILE`: includes the contents of `FILE` at the
|
||||
- `--html-in-header FILE`: includes the contents of `FILE` at the
|
||||
end of the `<head>...</head>` section.
|
||||
- `--markdown-before-content FILE`: includes the contents of `FILE`
|
||||
- `--html-before-content FILE`: includes the contents of `FILE`
|
||||
directly after `<body>`, before the rendered content (including the
|
||||
title).
|
||||
- `--markdown-after-content FILE`: includes the contents of `FILE`
|
||||
- `--html-after-content FILE`: includes the contents of `FILE`
|
||||
directly before `</body>`, after all the rendered content.
|
||||
|
||||
All of these can be specified multiple times, and they are output in
|
||||
the order in which they are specified. The first line of the file must
|
||||
the order in which they are specified. The first line of the file being rendered must
|
||||
be the title, prefixed with `%` (e.g. this page has `% Rust
|
||||
Documentation` on the first line).
|
||||
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ write function, variable, and module names with lowercase letters, using
|
|||
underscores where they help readability, while writing types in camel case.
|
||||
|
||||
~~~
|
||||
let my_variable = 100;
|
||||
let my_variable = 100i;
|
||||
type MyType = int; // primitive types are _not_ camel case
|
||||
~~~
|
||||
|
||||
|
|
@ -276,7 +276,7 @@ write a piece of code like this:
|
|||
|
||||
~~~~
|
||||
# let item = "salad";
|
||||
let price;
|
||||
let price: f64;
|
||||
if item == "salad" {
|
||||
price = 3.50;
|
||||
} else if item == "muffin" {
|
||||
|
|
@ -290,7 +290,7 @@ But, in Rust, you don't have to repeat the name `price`:
|
|||
|
||||
~~~~
|
||||
# let item = "salad";
|
||||
let price =
|
||||
let price: f64 =
|
||||
if item == "salad" {
|
||||
3.50
|
||||
} else if item == "muffin" {
|
||||
|
|
@ -337,11 +337,10 @@ suffix that can be used to indicate the type of a literal: `i` for `int`,
|
|||
In the absence of an integer literal suffix, Rust will infer the
|
||||
integer type based on type annotations and function signatures in the
|
||||
surrounding program. In the absence of any type information at all,
|
||||
Rust will assume that an unsuffixed integer literal has type
|
||||
`int`.
|
||||
Rust will report an error and request that the type be specified explicitly.
|
||||
|
||||
~~~~
|
||||
let a = 1; // `a` is an `int`
|
||||
let a: int = 1; // `a` is an `int`
|
||||
let b = 10i; // `b` is an `int`, due to the `i` suffix
|
||||
let c = 100u; // `c` is a `uint`
|
||||
let d = 1000i32; // `d` is an `i32`
|
||||
|
|
@ -475,7 +474,7 @@ against each pattern in order until one matches. The matching pattern
|
|||
executes its corresponding arm.
|
||||
|
||||
~~~~
|
||||
let my_number = 1;
|
||||
let my_number = 1i;
|
||||
match my_number {
|
||||
0 => println!("zero"),
|
||||
1 | 2 => println!("one or two"),
|
||||
|
|
@ -501,7 +500,7 @@ matches any single value. (`..`) is a different wildcard that can match
|
|||
one or more fields in an `enum` variant.
|
||||
|
||||
~~~
|
||||
# let my_number = 1;
|
||||
# let my_number = 1i;
|
||||
match my_number {
|
||||
0 => { println!("zero") }
|
||||
_ => { println!("something else") }
|
||||
|
|
@ -584,7 +583,7 @@ keyword `break` aborts the loop, and `continue` aborts the current
|
|||
iteration and continues with the next.
|
||||
|
||||
~~~~
|
||||
let mut cake_amount = 8;
|
||||
let mut cake_amount = 8i;
|
||||
while cake_amount > 0 {
|
||||
cake_amount -= 1;
|
||||
}
|
||||
|
|
@ -944,7 +943,7 @@ The `box` operator performs memory allocation on the heap:
|
|||
~~~~
|
||||
{
|
||||
// an integer allocated on the heap
|
||||
let y = box 10;
|
||||
let y = box 10i;
|
||||
}
|
||||
// the destructor frees the heap memory as soon as `y` goes out of scope
|
||||
~~~~
|
||||
|
|
@ -1165,7 +1164,7 @@ let z = x;
|
|||
The mutability of a value may be changed by moving it to a new owner:
|
||||
|
||||
~~~~
|
||||
let r = box 13;
|
||||
let r = box 13i;
|
||||
let mut s = r; // box becomes mutable
|
||||
*s += 1;
|
||||
let t = s; // box becomes immutable
|
||||
|
|
@ -1285,9 +1284,9 @@ Using the generic `List<T>` works much like before, thanks to type inference:
|
|||
# Cons(value, box xs)
|
||||
# }
|
||||
let mut xs = Nil; // Unknown type! This is a `List<T>`, but `T` can be anything.
|
||||
xs = prepend(xs, 10); // Here the compiler infers `xs`'s type as `List<int>`.
|
||||
xs = prepend(xs, 15);
|
||||
xs = prepend(xs, 20);
|
||||
xs = prepend(xs, 10i); // Here the compiler infers `xs`'s type as `List<int>`.
|
||||
xs = prepend(xs, 15i);
|
||||
xs = prepend(xs, 20i);
|
||||
~~~
|
||||
|
||||
The code sample above demonstrates type inference making most type annotations optional. It is
|
||||
|
|
@ -1410,12 +1409,12 @@ Beyond the properties granted by the size, an owned box behaves as a regular
|
|||
value by inheriting the mutability and lifetime of the owner:
|
||||
|
||||
~~~~
|
||||
let x = 5; // immutable
|
||||
let mut y = 5; // mutable
|
||||
let x = 5i; // immutable
|
||||
let mut y = 5i; // mutable
|
||||
y += 2;
|
||||
|
||||
let x = box 5; // immutable
|
||||
let mut y = box 5; // mutable
|
||||
let x = box 5i; // immutable
|
||||
let mut y = box 5i; // mutable
|
||||
*y += 2; // the `*` operator is needed to access the contained value
|
||||
~~~~
|
||||
|
||||
|
|
@ -1507,7 +1506,7 @@ freezing enforced statically at compile-time. An example of a non-`Freeze` type
|
|||
is [`RefCell<T>`][refcell].
|
||||
|
||||
~~~~
|
||||
let mut x = 5;
|
||||
let mut x = 5i;
|
||||
{
|
||||
let y = &x; // `x` is now frozen. It cannot be modified or re-assigned.
|
||||
}
|
||||
|
|
@ -1523,8 +1522,8 @@ Rust uses the unary star operator (`*`) to access the contents of a
|
|||
box or pointer, similarly to C.
|
||||
|
||||
~~~
|
||||
let owned = box 10;
|
||||
let borrowed = &20;
|
||||
let owned = box 10i;
|
||||
let borrowed = &20i;
|
||||
|
||||
let sum = *owned + *borrowed;
|
||||
~~~
|
||||
|
|
@ -1534,9 +1533,9 @@ assignments. Such an assignment modifies the value that the pointer
|
|||
points to.
|
||||
|
||||
~~~
|
||||
let mut owned = box 10;
|
||||
let mut owned = box 10i;
|
||||
|
||||
let mut value = 20;
|
||||
let mut value = 20i;
|
||||
let borrowed = &mut value;
|
||||
|
||||
*owned = *borrowed + 100;
|
||||
|
|
@ -1654,12 +1653,12 @@ Unicode code points, so they cannot be freely mutated without the ability to
|
|||
alter the length.
|
||||
|
||||
~~~
|
||||
let mut xs = [1, 2, 3];
|
||||
let mut xs = [1i, 2i, 3i];
|
||||
let view = xs.mut_slice(0, 2);
|
||||
view[0] = 5;
|
||||
|
||||
// The type of a mutable slice is written as `&mut [T]`
|
||||
let ys: &mut [int] = &mut [1, 2, 3];
|
||||
let ys: &mut [int] = &mut [1i, 2i, 3i];
|
||||
~~~
|
||||
|
||||
Square brackets denote indexing into a slice or fixed-size vector:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue