mirror of https://github.com/rust-lang/rust.git
auto merge of #21300 : steveklabnik/rust/rollup, r=steveklabnik
manual rollup to fix some conflicts and diagnose why the test is failing...
This commit is contained in:
commit
f4f10dba29
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2014 The Rust Project Developers
|
||||
Copyright (c) 2015 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
TARGET_CRATES := libc std flate arena term \
|
||||
serialize getopts collections test rand \
|
||||
log regex graphviz core rbml alloc \
|
||||
unicode
|
||||
unicode rustc_bitflags
|
||||
RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
|
||||
rustc_trans rustc_back rustc_llvm rustc_privacy
|
||||
HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
|
||||
|
@ -64,7 +64,8 @@ DEPS_libc := core
|
|||
DEPS_unicode := core
|
||||
DEPS_alloc := core libc native:jemalloc
|
||||
DEPS_std := core libc rand alloc collections unicode \
|
||||
native:rust_builtin native:backtrace native:rustrt_native
|
||||
native:rust_builtin native:backtrace native:rustrt_native \
|
||||
rustc_bitflags
|
||||
DEPS_graphviz := std
|
||||
DEPS_syntax := std term serialize log fmt_macros arena libc
|
||||
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
|
||||
|
@ -83,6 +84,7 @@ DEPS_rustc_llvm := native:rustllvm libc std
|
|||
DEPS_rustc_back := std syntax rustc_llvm flate log libc
|
||||
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
|
||||
test
|
||||
DEPS_rustc_bitflags := core
|
||||
DEPS_flate := std native:miniz
|
||||
DEPS_arena := std
|
||||
DEPS_graphviz := std
|
||||
|
@ -114,6 +116,7 @@ ONLY_RLIB_alloc := 1
|
|||
ONLY_RLIB_rand := 1
|
||||
ONLY_RLIB_collections := 1
|
||||
ONLY_RLIB_unicode := 1
|
||||
ONLY_RLIB_rustc_bitflags := 1
|
||||
|
||||
################################################################################
|
||||
# You should not need to edit below this line
|
||||
|
|
|
@ -424,11 +424,11 @@ Let's see an example. This Rust code will not compile:
|
|||
use std::thread::Thread;
|
||||
|
||||
fn main() {
|
||||
let mut numbers = vec![1i, 2i, 3i];
|
||||
let mut numbers = vec![1is, 2, 3];
|
||||
|
||||
for i in range(0u, 3u) {
|
||||
for i in 0..3 {
|
||||
Thread::spawn(move || {
|
||||
for j in range(0, 3) { numbers[j] += 1 }
|
||||
for j in 0..3 { numbers[j] += 1 }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -438,15 +438,15 @@ It gives us this error:
|
|||
|
||||
```text
|
||||
6:71 error: capture of moved value: `numbers`
|
||||
for j in range(0, 3) { numbers[j] += 1 }
|
||||
^~~~~~~
|
||||
for j in 0..3 { numbers[j] += 1 }
|
||||
^~~~~~~
|
||||
7:50 note: `numbers` moved into closure environment here
|
||||
spawn(move || {
|
||||
for j in range(0, 3) { numbers[j] += 1 }
|
||||
for j in 0..3 { numbers[j] += 1 }
|
||||
});
|
||||
6:79 error: cannot assign to immutable dereference (dereference is implicit, due to indexing)
|
||||
for j in range(0, 3) { numbers[j] += 1 }
|
||||
^~~~~~~~~~~~~~~
|
||||
for j in 0..3 { numbers[j] += 1 }
|
||||
^~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
It mentions that "numbers moved into closure environment". Because we
|
||||
|
@ -478,9 +478,9 @@ use std::thread::Thread;
|
|||
use std::sync::{Arc,Mutex};
|
||||
|
||||
fn main() {
|
||||
let numbers = Arc::new(Mutex::new(vec![1i, 2i, 3i]));
|
||||
let numbers = Arc::new(Mutex::new(vec![1is, 2, 3]));
|
||||
|
||||
for i in range(0u, 3u) {
|
||||
for i in 0..3 {
|
||||
let number = numbers.clone();
|
||||
Thread::spawn(move || {
|
||||
let mut array = number.lock().unwrap();
|
||||
|
@ -541,12 +541,12 @@ safety check that makes this an error about moved values:
|
|||
use std::thread::Thread;
|
||||
|
||||
fn main() {
|
||||
let vec = vec![1i, 2, 3];
|
||||
let vec = vec![1is, 2, 3];
|
||||
|
||||
for i in range(0u, 3) {
|
||||
for i in 0us..3 {
|
||||
Thread::spawn(move || {
|
||||
println!("{}", vec[i]);
|
||||
}).detach();
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -557,9 +557,9 @@ you can remove it. As an example, this is a poor way to iterate through
|
|||
a vector:
|
||||
|
||||
```{rust}
|
||||
let vec = vec![1i, 2, 3];
|
||||
let vec = vec![1, 2, 3];
|
||||
|
||||
for i in range(0u, vec.len()) {
|
||||
for i in 0..vec.len() {
|
||||
println!("{}", vec[i]);
|
||||
}
|
||||
```
|
||||
|
@ -569,7 +569,7 @@ that we don't try to access an invalid index. However, we can remove this
|
|||
while retaining safety. The answer is iterators:
|
||||
|
||||
```{rust}
|
||||
let vec = vec![1i, 2, 3];
|
||||
let vec = vec![1, 2, 3];
|
||||
|
||||
for x in vec.iter() {
|
||||
println!("{}", x);
|
||||
|
|
|
@ -1413,6 +1413,27 @@ a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 };
|
|||
In this example, `Cat` is a _struct-like enum variant_,
|
||||
whereas `Dog` is simply called an enum variant.
|
||||
|
||||
Enums have a discriminant. You can assign them explicitly:
|
||||
|
||||
```
|
||||
enum Foo {
|
||||
Bar = 123,
|
||||
}
|
||||
```
|
||||
|
||||
If a discriminant isn't assigned, they start at zero, and add one for each
|
||||
variant, in order.
|
||||
|
||||
You can cast an enum to get this value:
|
||||
|
||||
```
|
||||
# enum Foo { Bar = 123 }
|
||||
let x = Foo::Bar as u32; // x is now 123u32
|
||||
```
|
||||
|
||||
This only works as long as none of the variants have data attached. If
|
||||
it were `Bar(i32)`, this is disallowed.
|
||||
|
||||
### Constant items
|
||||
|
||||
```{.ebnf .gram}
|
||||
|
|
|
@ -5,7 +5,7 @@ things. The most basic is the *array*, a fixed-size list of elements of the
|
|||
same type. By default, arrays are immutable.
|
||||
|
||||
```{rust}
|
||||
let a = [1, 2, 3]; // a: [i32; 3]
|
||||
let a = [1, 2, 3]; // a: [i32; 3]
|
||||
let mut m = [1, 2, 3]; // mut m: [i32; 3]
|
||||
```
|
||||
|
||||
|
@ -68,7 +68,7 @@ let mut nums = vec![1, 2, 3]; // mut nums: Vec<i32>
|
|||
|
||||
nums.push(4);
|
||||
|
||||
println!("The length of nums is now {}", nums.len()); // Prints 4
|
||||
println!("The length of nums is now {}", nums.len()); // Prints 4
|
||||
```
|
||||
|
||||
Vectors have many more useful methods.
|
||||
|
@ -82,10 +82,10 @@ arrays:
|
|||
|
||||
```{rust}
|
||||
let a = [0, 1, 2, 3, 4];
|
||||
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
|
||||
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
|
||||
|
||||
for e in middle.iter() {
|
||||
println!("{}", e); // Prints 1, 2, 3
|
||||
println!("{}", e); // Prints 1, 2, 3
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ arity and contained types.
|
|||
|
||||
```rust
|
||||
let mut x = (1, 2); // x: (i32, i32)
|
||||
let y = (2, 3); // y: (i32, i32)
|
||||
let y = (2, 3); // y: (i32, i32)
|
||||
|
||||
x = y;
|
||||
```
|
||||
|
@ -156,7 +156,7 @@ These two will not be equal, even if they have the same values:
|
|||
```{rust}
|
||||
# struct Color(i32, i32, i32);
|
||||
# struct Point(i32, i32, i32);
|
||||
let black = Color(0, 0, 0);
|
||||
let black = Color(0, 0, 0);
|
||||
let origin = Point(0, 0, 0);
|
||||
```
|
||||
|
||||
|
@ -297,7 +297,7 @@ enum StringResult {
|
|||
}
|
||||
```
|
||||
Where a `StringResult` is either a `StringResult::StringOK`, with the result of
|
||||
a computation, or an `StringResult::ErrorReason` with a `String` explaining
|
||||
a computation, or a `StringResult::ErrorReason` with a `String` explaining
|
||||
what caused the computation to fail. These kinds of `enum`s are actually very
|
||||
useful and are even part of the standard library.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% The Rust Crates and Modules Guide
|
||||
% Crates and Modules
|
||||
|
||||
When a project starts getting large, it's considered a good software
|
||||
engineering practice to split it up into a bunch of smaller pieces, and then
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% Error Handling in Rust
|
||||
% Error Handling
|
||||
|
||||
> The best-laid plans of mice and men
|
||||
> Often go awry
|
||||
|
@ -60,12 +60,12 @@ fn probability(_: &Event) -> f64 {
|
|||
|
||||
fn descriptive_probability(event: Event) -> &'static str {
|
||||
match probability(&event) {
|
||||
1.00 => "certain",
|
||||
0.00 => "impossible",
|
||||
1.00 => "certain",
|
||||
0.00 => "impossible",
|
||||
0.00 ... 0.25 => "very unlikely",
|
||||
0.25 ... 0.50 => "unlikely",
|
||||
0.50 ... 0.75 => "likely",
|
||||
0.75 ... 1.00 => "very likely",
|
||||
0.75 ... 1.00 => "very likely",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,12 +97,12 @@ fn probability(_: &Event) -> f64 {
|
|||
|
||||
fn descriptive_probability(event: Event) -> &'static str {
|
||||
match probability(&event) {
|
||||
1.00 => "certain",
|
||||
0.00 => "impossible",
|
||||
1.00 => "certain",
|
||||
0.00 => "impossible",
|
||||
0.00 ... 0.25 => "very unlikely",
|
||||
0.25 ... 0.50 => "unlikely",
|
||||
0.50 ... 0.75 => "likely",
|
||||
0.75 ... 1.00 => "very likely",
|
||||
0.75 ... 1.00 => "very likely",
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% The Rust Foreign Function Interface Guide
|
||||
% Foreign Function Interface
|
||||
|
||||
# Introduction
|
||||
|
||||
|
@ -11,7 +11,7 @@ snappy includes a C interface (documented in
|
|||
The following is a minimal example of calling a foreign function which will
|
||||
compile if snappy is installed:
|
||||
|
||||
~~~~no_run
|
||||
```no_run
|
||||
extern crate libc;
|
||||
use libc::size_t;
|
||||
|
||||
|
@ -24,7 +24,7 @@ fn main() {
|
|||
let x = unsafe { snappy_max_compressed_length(100) };
|
||||
println!("max compressed length of a 100 byte buffer: {}", x);
|
||||
}
|
||||
~~~~
|
||||
```
|
||||
|
||||
The `extern` block is a list of function signatures in a foreign library, in
|
||||
this case with the platform's C ABI. The `#[link(...)]` attribute is used to
|
||||
|
@ -44,7 +44,7 @@ keeping the binding correct at runtime.
|
|||
|
||||
The `extern` block can be extended to cover the entire snappy API:
|
||||
|
||||
~~~~no_run
|
||||
```no_run
|
||||
extern crate libc;
|
||||
use libc::{c_int, size_t};
|
||||
|
||||
|
@ -66,7 +66,7 @@ extern {
|
|||
compressed_length: size_t) -> c_int;
|
||||
}
|
||||
# fn main() {}
|
||||
~~~~
|
||||
```
|
||||
|
||||
# Creating a safe interface
|
||||
|
||||
|
@ -79,7 +79,7 @@ vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous
|
|||
length is number of elements currently contained, and the capacity is the total size in elements of
|
||||
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(_: *const u8, _: size_t) -> c_int { 0 }
|
||||
|
@ -89,7 +89,7 @@ pub fn validate_compressed_buffer(src: &[u8]) -> bool {
|
|||
snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
```
|
||||
|
||||
The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the
|
||||
guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function
|
||||
|
@ -103,7 +103,7 @@ required capacity to hold the compressed output. The vector can then be passed t
|
|||
`snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
|
||||
the true length after compression for setting the length.
|
||||
|
||||
~~~~
|
||||
```
|
||||
# extern crate libc;
|
||||
# use libc::{size_t, c_int};
|
||||
# unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8,
|
||||
|
@ -116,20 +116,20 @@ pub fn compress(src: &[u8]) -> Vec<u8> {
|
|||
let psrc = src.as_ptr();
|
||||
|
||||
let mut dstlen = snappy_max_compressed_length(srclen);
|
||||
let mut dst = Vec::with_capacity(dstlen as uint);
|
||||
let mut dst = Vec::with_capacity(dstlen as usize);
|
||||
let pdst = dst.as_mut_ptr();
|
||||
|
||||
snappy_compress(psrc, srclen, pdst, &mut dstlen);
|
||||
dst.set_len(dstlen as uint);
|
||||
dst.set_len(dstlen as usize);
|
||||
dst
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
```
|
||||
|
||||
Decompression is similar, because snappy stores the uncompressed size as part of the compression
|
||||
format and `snappy_uncompressed_length` will retrieve the exact buffer size required.
|
||||
|
||||
~~~~
|
||||
```
|
||||
# extern crate libc;
|
||||
# use libc::{size_t, c_int};
|
||||
# unsafe fn snappy_uncompress(compressed: *const u8,
|
||||
|
@ -148,45 +148,22 @@ pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> {
|
|||
let mut dstlen: size_t = 0;
|
||||
snappy_uncompressed_length(psrc, srclen, &mut dstlen);
|
||||
|
||||
let mut dst = Vec::with_capacity(dstlen as uint);
|
||||
let mut dst = Vec::with_capacity(dstlen as usize);
|
||||
let pdst = dst.as_mut_ptr();
|
||||
|
||||
if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {
|
||||
dst.set_len(dstlen as uint);
|
||||
dst.set_len(dstlen as usize);
|
||||
Some(dst)
|
||||
} else {
|
||||
None // SNAPPY_INVALID_INPUT
|
||||
}
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
```
|
||||
|
||||
For reference, the examples used here are also available as an [library on
|
||||
GitHub](https://github.com/thestinger/rust-snappy).
|
||||
|
||||
# Stack management
|
||||
|
||||
Rust threads by default run on a *large stack*. This is actually implemented as a
|
||||
reserving a large segment of the address space and then lazily mapping in pages
|
||||
as they are needed. When calling an external C function, the code is invoked on
|
||||
the same stack as the rust stack. This means that there is no extra
|
||||
stack-switching mechanism in place because it is assumed that the large stack
|
||||
for the rust thread is plenty for the C function to have.
|
||||
|
||||
A planned future improvement (not yet implemented at the time of this writing)
|
||||
is to have a guard page at the end of every rust stack. No rust function will
|
||||
hit this guard page (due to Rust's usage of LLVM's `__morestack`). The intention
|
||||
for this unmapped page is to prevent infinite recursion in C from overflowing
|
||||
onto other rust stacks. If the guard page is hit, then the process will be
|
||||
terminated with a message saying that the guard page was hit.
|
||||
|
||||
For normal external function usage, this all means that there shouldn't be any
|
||||
need for any extra effort on a user's perspective. The C stack naturally
|
||||
interleaves with the rust stack, and it's "large enough" for both to
|
||||
interoperate. If, however, it is determined that a larger stack is necessary,
|
||||
there are appropriate functions in the thread spawning API to control the size of
|
||||
the stack of the thread which is spawned.
|
||||
|
||||
# Destructors
|
||||
|
||||
Foreign libraries often hand off ownership of resources to the calling code.
|
||||
|
@ -208,7 +185,7 @@ A basic example is:
|
|||
|
||||
Rust code:
|
||||
|
||||
~~~~no_run
|
||||
```no_run
|
||||
extern fn callback(a: i32) {
|
||||
println!("I'm called from C with value {0}", a);
|
||||
}
|
||||
|
@ -225,11 +202,11 @@ fn main() {
|
|||
trigger_callback(); // Triggers the callback
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
```
|
||||
|
||||
C code:
|
||||
|
||||
~~~~c
|
||||
```c
|
||||
typedef void (*rust_callback)(int32_t);
|
||||
rust_callback cb;
|
||||
|
||||
|
@ -241,7 +218,7 @@ int32_t register_callback(rust_callback callback) {
|
|||
void trigger_callback() {
|
||||
cb(7); // Will call callback(7) in Rust
|
||||
}
|
||||
~~~~
|
||||
```
|
||||
|
||||
In this example Rust's `main()` will call `trigger_callback()` in C,
|
||||
which would, in turn, call back to `callback()` in Rust.
|
||||
|
@ -261,7 +238,7 @@ referenced Rust object.
|
|||
|
||||
Rust code:
|
||||
|
||||
~~~~no_run
|
||||
```no_run
|
||||
#[repr(C)]
|
||||
struct RustObject {
|
||||
a: i32,
|
||||
|
@ -292,11 +269,11 @@ fn main() {
|
|||
trigger_callback();
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
```
|
||||
|
||||
C code:
|
||||
|
||||
~~~~c
|
||||
```c
|
||||
typedef void (*rust_callback)(void*, int32_t);
|
||||
void* cb_target;
|
||||
rust_callback cb;
|
||||
|
@ -310,7 +287,7 @@ int32_t register_callback(void* callback_target, rust_callback callback) {
|
|||
void trigger_callback() {
|
||||
cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust
|
||||
}
|
||||
~~~~
|
||||
```
|
||||
|
||||
## Asynchronous callbacks
|
||||
|
||||
|
@ -389,13 +366,13 @@ the `link_args` attribute. This attribute is applied to `extern` blocks and
|
|||
specifies raw flags which need to get passed to the linker when producing an
|
||||
artifact. An example usage would be:
|
||||
|
||||
~~~ no_run
|
||||
``` no_run
|
||||
#![feature(link_args)]
|
||||
|
||||
#[link_args = "-foo -bar -baz"]
|
||||
extern {}
|
||||
# fn main() {}
|
||||
~~~
|
||||
```
|
||||
|
||||
Note that this feature is currently hidden behind the `feature(link_args)` gate
|
||||
because this is not a sanctioned way of performing linking. Right now rustc
|
||||
|
@ -416,9 +393,9 @@ the compiler that the unsafety does not leak out of the block.
|
|||
Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like
|
||||
this:
|
||||
|
||||
~~~~
|
||||
```
|
||||
unsafe fn kaboom(ptr: *const int) -> int { *ptr }
|
||||
~~~~
|
||||
```
|
||||
|
||||
This function can only be called from an `unsafe` block or another `unsafe` function.
|
||||
|
||||
|
@ -428,7 +405,7 @@ Foreign APIs often export a global variable which could do something like track
|
|||
global state. In order to access these variables, you declare them in `extern`
|
||||
blocks with the `static` keyword:
|
||||
|
||||
~~~no_run
|
||||
```no_run
|
||||
extern crate libc;
|
||||
|
||||
#[link(name = "readline")]
|
||||
|
@ -440,13 +417,13 @@ fn main() {
|
|||
println!("You have readline version {} installed.",
|
||||
rl_readline_version as int);
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
Alternatively, you may need to alter global state provided by a foreign
|
||||
interface. To do this, statics can be declared with `mut` so rust can mutate
|
||||
them.
|
||||
|
||||
~~~no_run
|
||||
```no_run
|
||||
extern crate libc;
|
||||
|
||||
use std::ffi::CString;
|
||||
|
@ -463,7 +440,7 @@ fn main() {
|
|||
// get a line, process it
|
||||
unsafe { rl_prompt = ptr::null(); }
|
||||
}
|
||||
~~~
|
||||
```
|
||||
|
||||
# Foreign calling conventions
|
||||
|
||||
|
@ -471,7 +448,7 @@ Most foreign code exposes a C ABI, and Rust uses the platform's C calling conven
|
|||
calling foreign functions. Some foreign functions, most notably the Windows API, use other calling
|
||||
conventions. Rust provides a way to tell the compiler which convention to use:
|
||||
|
||||
~~~~
|
||||
```
|
||||
extern crate libc;
|
||||
|
||||
#[cfg(all(target_os = "win32", target_arch = "x86"))]
|
||||
|
@ -481,7 +458,7 @@ extern "stdcall" {
|
|||
fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int;
|
||||
}
|
||||
# fn main() { }
|
||||
~~~~
|
||||
```
|
||||
|
||||
This applies to the entire `extern` block. The list of supported ABI constraints
|
||||
are:
|
||||
|
@ -541,3 +518,22 @@ with one of the non-nullable types, it is represented as a single pointer,
|
|||
and the non-data variant is represented as the null pointer. So
|
||||
`Option<extern "C" fn(c_int) -> c_int>` is how one represents a nullable
|
||||
function pointer using the C ABI.
|
||||
|
||||
# Calling Rust code from C
|
||||
|
||||
You may wish to compile Rust code in a way so that it can be called from C. This is
|
||||
fairly easy, but requires a few things:
|
||||
|
||||
```
|
||||
#[no_mangle]
|
||||
pub extern fn hello_rust() -> *const u8 {
|
||||
"Hello, world!\0".as_ptr()
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
The `extern` makes this function adhere to the C calling convention, as
|
||||
discussed above in "[Foreign Calling
|
||||
Conventions](guide-ffi.html#foreign-calling-conventions)". The `no_mangle`
|
||||
attribute turns off Rust's name mangling, so that it is easier to link to.
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ fn foo(x: i32) -> i32 {
|
|||
```
|
||||
|
||||
The previous definition without `return` may look a bit strange if you haven't
|
||||
worked in an expression-based language before, but it becomes intutive over
|
||||
worked in an expression-based language before, but it becomes intuitive over
|
||||
time. If this were production code, we wouldn't write it in that way anyway,
|
||||
we'd write this:
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ multiple types of arguments. For example, remember our `OptionalInt` type?
|
|||
|
||||
```{rust}
|
||||
enum OptionalInt {
|
||||
Value(int),
|
||||
Value(i32),
|
||||
Missing,
|
||||
}
|
||||
```
|
||||
|
@ -40,26 +40,26 @@ we substitute that type for the same type used in the generic. Here's an
|
|||
example of using `Option<T>`, with some extra type annotations:
|
||||
|
||||
```{rust}
|
||||
let x: Option<int> = Some(5i);
|
||||
let x: Option<i32> = Some(5);
|
||||
```
|
||||
|
||||
In the type declaration, we say `Option<int>`. Note how similar this looks to
|
||||
`Option<T>`. So, in this particular `Option`, `T` has the value of `int`. On
|
||||
the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5i`.
|
||||
Since that's an `int`, the two sides match, and Rust is happy. If they didn't
|
||||
In the type declaration, we say `Option<i32>`. Note how similar this looks to
|
||||
`Option<T>`. 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:
|
||||
|
||||
```{rust,ignore}
|
||||
let x: Option<f64> = Some(5i);
|
||||
// error: mismatched types: expected `core::option::Option<f64>`
|
||||
// but found `core::option::Option<int>` (expected f64 but found int)
|
||||
let x: Option<f64> = Some(5);
|
||||
// error: mismatched types: expected `core::option::Option<f64>`,
|
||||
// found `core::option::Option<_>` (expected f64 but found integral variable)
|
||||
```
|
||||
|
||||
That doesn't mean we can't make `Option<T>`s that hold an `f64`! They just have to
|
||||
match up:
|
||||
|
||||
```{rust}
|
||||
let x: Option<int> = Some(5i);
|
||||
let x: Option<i32> = Some(5);
|
||||
let y: Option<f64> = Some(5.0f64);
|
||||
```
|
||||
|
||||
|
|
|
@ -297,9 +297,9 @@ fn main() {
|
|||
println!("You guessed: {}", input);
|
||||
|
||||
match cmp(input, secret_number) {
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Greater => println!("Too big!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,9 +352,9 @@ fn main() {
|
|||
println!("You guessed: {}", input);
|
||||
|
||||
match cmp(input, secret_number) {
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Greater => println!("Too big!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,8 +422,8 @@ In this case, we say `x` is a `u32` explicitly, so Rust is able to properly
|
|||
tell `random()` what to generate. In a similar fashion, both of these work:
|
||||
|
||||
```{rust,ignore}
|
||||
let input_num = "5".parse::<u32>(); // input_num: Option<u32>
|
||||
let input_num: Option<u32> = "5".parse(); // input_num: Option<u32>
|
||||
let input_num = "5".parse::<u32>(); // input_num: Option<u32>
|
||||
let input_num: Option<u32> = "5".parse(); // input_num: Option<u32>
|
||||
```
|
||||
|
||||
Anyway, with us now converting our input to a number, our code looks like this:
|
||||
|
@ -450,9 +450,9 @@ fn main() {
|
|||
println!("You guessed: {}", input_num);
|
||||
|
||||
match cmp(input_num, secret_number) {
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Greater => println!("Too big!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,7 +499,7 @@ fn main() {
|
|||
|
||||
let num = match input_num {
|
||||
Some(num) => num,
|
||||
None => {
|
||||
None => {
|
||||
println!("Please input a number!");
|
||||
return;
|
||||
}
|
||||
|
@ -509,9 +509,9 @@ fn main() {
|
|||
println!("You guessed: {}", num);
|
||||
|
||||
match cmp(num, secret_number) {
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Greater => println!("Too big!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -566,7 +566,7 @@ fn main() {
|
|||
|
||||
let num = match input_num {
|
||||
Some(num) => num,
|
||||
None => {
|
||||
None => {
|
||||
println!("Please input a number!");
|
||||
return;
|
||||
}
|
||||
|
@ -576,9 +576,9 @@ fn main() {
|
|||
println!("You guessed: {}", num);
|
||||
|
||||
match cmp(num, secret_number) {
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Greater => println!("Too big!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -642,7 +642,7 @@ fn main() {
|
|||
|
||||
let num = match input_num {
|
||||
Some(num) => num,
|
||||
None => {
|
||||
None => {
|
||||
println!("Please input a number!");
|
||||
return;
|
||||
}
|
||||
|
@ -652,9 +652,9 @@ fn main() {
|
|||
println!("You guessed: {}", num);
|
||||
|
||||
match cmp(num, secret_number) {
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Greater => println!("Too big!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
Ordering::Equal => println!("You win!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -718,7 +718,7 @@ fn main() {
|
|||
|
||||
let num = match input_num {
|
||||
Some(num) => num,
|
||||
None => {
|
||||
None => {
|
||||
println!("Please input a number!");
|
||||
return;
|
||||
}
|
||||
|
@ -728,9 +728,9 @@ fn main() {
|
|||
println!("You guessed: {}", num);
|
||||
|
||||
match cmp(num, secret_number) {
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Greater => println!("Too big!"),
|
||||
Ordering::Equal => {
|
||||
Ordering::Equal => {
|
||||
println!("You win!");
|
||||
return;
|
||||
},
|
||||
|
@ -774,7 +774,7 @@ fn main() {
|
|||
|
||||
let num = match input_num {
|
||||
Some(num) => num,
|
||||
None => {
|
||||
None => {
|
||||
println!("Please input a number!");
|
||||
continue;
|
||||
}
|
||||
|
@ -784,9 +784,9 @@ fn main() {
|
|||
println!("You guessed: {}", num);
|
||||
|
||||
match cmp(num, secret_number) {
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Greater => println!("Too big!"),
|
||||
Ordering::Equal => {
|
||||
Ordering::Equal => {
|
||||
println!("You win!");
|
||||
return;
|
||||
},
|
||||
|
@ -851,7 +851,7 @@ fn main() {
|
|||
|
||||
let num = match input_num {
|
||||
Some(num) => num,
|
||||
None => {
|
||||
None => {
|
||||
println!("Please input a number!");
|
||||
continue;
|
||||
}
|
||||
|
@ -861,9 +861,9 @@ fn main() {
|
|||
println!("You guessed: {}", num);
|
||||
|
||||
match cmp(num, secret_number) {
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Less => println!("Too small!"),
|
||||
Ordering::Greater => println!("Too big!"),
|
||||
Ordering::Equal => {
|
||||
Ordering::Equal => {
|
||||
println!("You win!");
|
||||
return;
|
||||
},
|
||||
|
|
|
@ -5,7 +5,7 @@ Let's talk about loops.
|
|||
Remember Rust's `for` loop? Here's an example:
|
||||
|
||||
```{rust}
|
||||
for x in range(0i, 10i) {
|
||||
for x in range(0, 10) {
|
||||
println!("{}", x);
|
||||
}
|
||||
```
|
||||
|
@ -17,7 +17,7 @@ call the `.next()` method on repeatedly, and it gives us a sequence of things.
|
|||
Like this:
|
||||
|
||||
```{rust}
|
||||
let mut range = range(0i, 10i);
|
||||
let mut range = range(0, 10);
|
||||
|
||||
loop {
|
||||
match range.next() {
|
||||
|
@ -32,8 +32,8 @@ loop {
|
|||
We make a mutable binding to the return value of `range`, which is our iterator.
|
||||
We then `loop`, with an inner `match`. This `match` is used on the result of
|
||||
`range.next()`, which gives us a reference to the next value of the iterator.
|
||||
`next` returns an `Option<int>`, in this case, which will be `Some(int)` when
|
||||
we have a value and `None` once we run out. If we get `Some(int)`, we print it
|
||||
`next` returns an `Option<i32>`, in this case, which will be `Some(i32)` when
|
||||
we have a value and `None` once we run out. If we get `Some(i32)`, we print it
|
||||
out, and if we get `None`, we `break` out of the loop.
|
||||
|
||||
This code sample is basically the same as our `for` loop version. The `for`
|
||||
|
@ -50,9 +50,9 @@ primitive. For example, if you needed to iterate over the contents of
|
|||
a vector, you may be tempted to write this:
|
||||
|
||||
```{rust}
|
||||
let nums = vec![1i, 2i, 3i];
|
||||
let nums = vec![1, 2, 3];
|
||||
|
||||
for i in range(0u, nums.len()) {
|
||||
for i in range(0, nums.len()) {
|
||||
println!("{}", nums[i]);
|
||||
}
|
||||
```
|
||||
|
@ -62,7 +62,7 @@ vectors returns an iterator which iterates through a reference to each element
|
|||
of the vector in turn. So write this:
|
||||
|
||||
```{rust}
|
||||
let nums = vec![1i, 2i, 3i];
|
||||
let nums = vec![1, 2, 3];
|
||||
|
||||
for num in nums.iter() {
|
||||
println!("{}", num);
|
||||
|
@ -79,12 +79,12 @@ very common with iterators: we can ignore unnecessary bounds checks, but still
|
|||
know that we're safe.
|
||||
|
||||
There's another detail here that's not 100% clear because of how `println!`
|
||||
works. `num` is actually of type `&int`. That is, it's a reference to an `int`,
|
||||
not an `int` itself. `println!` handles the dereferencing for us, so we don't
|
||||
works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`,
|
||||
not an `i32` itself. `println!` handles the dereferencing for us, so we don't
|
||||
see it. This code works fine too:
|
||||
|
||||
```{rust}
|
||||
let nums = vec![1i, 2i, 3i];
|
||||
let nums = vec![1, 2, 3];
|
||||
|
||||
for num in nums.iter() {
|
||||
println!("{}", *num);
|
||||
|
@ -118,7 +118,7 @@ The most common consumer is `collect()`. This code doesn't quite compile,
|
|||
but it shows the intention:
|
||||
|
||||
```{rust,ignore}
|
||||
let one_to_one_hundred = range(1i, 101i).collect();
|
||||
let one_to_one_hundred = range(1, 101).collect();
|
||||
```
|
||||
|
||||
As you can see, we call `collect()` on our iterator. `collect()` takes
|
||||
|
@ -128,7 +128,7 @@ type of things you want to collect, and so you need to let it know.
|
|||
Here's the version that does compile:
|
||||
|
||||
```{rust}
|
||||
let one_to_one_hundred = range(1i, 101i).collect::<Vec<int>>();
|
||||
let one_to_one_hundred = range(1, 101).collect::<Vec<i32>>();
|
||||
```
|
||||
|
||||
If you remember, the `::<>` syntax allows us to give a type hint,
|
||||
|
@ -138,12 +138,12 @@ and so we tell it that we want a vector of integers.
|
|||
is one:
|
||||
|
||||
```{rust}
|
||||
let greater_than_forty_two = range(0i, 100i)
|
||||
let greater_than_forty_two = range(0, 100)
|
||||
.find(|x| *x > 42);
|
||||
|
||||
match greater_than_forty_two {
|
||||
Some(_) => println!("We got some numbers!"),
|
||||
None => println!("No numbers found :("),
|
||||
None => println!("No numbers found :("),
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -155,8 +155,8 @@ element, `find` returns an `Option` rather than the element itself.
|
|||
Another important consumer is `fold`. Here's what it looks like:
|
||||
|
||||
```{rust}
|
||||
let sum = range(1i, 4i)
|
||||
.fold(0i, |sum, x| sum + x);
|
||||
let sum = range(1, 4)
|
||||
.fold(0, |sum, x| sum + x);
|
||||
```
|
||||
|
||||
`fold()` is a consumer that looks like this:
|
||||
|
@ -172,24 +172,24 @@ in this iterator:
|
|||
|
||||
| base | accumulator | element | closure result |
|
||||
|------|-------------|---------|----------------|
|
||||
| 0i | 0i | 1i | 1i |
|
||||
| 0i | 1i | 2i | 3i |
|
||||
| 0i | 3i | 3i | 6i |
|
||||
| 0 | 0 | 1 | 1 |
|
||||
| 0 | 1 | 2 | 3 |
|
||||
| 0 | 3 | 3 | 6 |
|
||||
|
||||
We called `fold()` with these arguments:
|
||||
|
||||
```{rust}
|
||||
# range(1i, 4i)
|
||||
.fold(0i, |sum, x| sum + x);
|
||||
# range(1, 4)
|
||||
.fold(0, |sum, x| sum + x);
|
||||
```
|
||||
|
||||
So, `0i` is our base, `sum` is our accumulator, and `x` is our element. On the
|
||||
first iteration, we set `sum` to `0i`, and `x` is the first element of `nums`,
|
||||
`1i`. We then add `sum` and `x`, which gives us `0i + 1i = 1i`. On the second
|
||||
So, `0` is our base, `sum` is our accumulator, and `x` is our element. On the
|
||||
first iteration, we set `sum` to `0`, and `x` is the first element of `nums`,
|
||||
`1`. We then add `sum` and `x`, which gives us `0 + 1 = 1`. On the second
|
||||
iteration, that value becomes our accumulator, `sum`, and the element is
|
||||
the second element of the array, `2i`. `1i + 2i = 3i`, and so that becomes
|
||||
the second element of the array, `2`. `1 + 2 = 3`, and so that becomes
|
||||
the value of the accumulator for the last iteration. On that iteration,
|
||||
`x` is the last element, `3i`, and `3i + 3i = 6i`, which is our final
|
||||
`x` is the last element, `3`, and `3 + 3 = 6`, which is our final
|
||||
result for our sum. `1 + 2 + 3 = 6`, and that's the result we got.
|
||||
|
||||
Whew. `fold` can be a bit strange the first few times you see it, but once it
|
||||
|
@ -210,14 +210,14 @@ This code, for example, does not actually generate the numbers
|
|||
`1-100`, and just creates a value that represents the sequence:
|
||||
|
||||
```{rust}
|
||||
let nums = range(1i, 100i);
|
||||
let nums = range(1, 100);
|
||||
```
|
||||
|
||||
Since we didn't do anything with the range, it didn't generate the sequence.
|
||||
Let's add the consumer:
|
||||
|
||||
```{rust}
|
||||
let nums = range(1i, 100i).collect::<Vec<int>>();
|
||||
let nums = range(1, 100).collect::<Vec<i32>>();
|
||||
```
|
||||
|
||||
Now, `collect()` will require that `range()` give it some numbers, and so
|
||||
|
@ -228,7 +228,7 @@ which you've used before. `iter()` can turn a vector into a simple iterator
|
|||
that gives you each element in turn:
|
||||
|
||||
```{rust}
|
||||
let nums = [1i, 2i, 3i];
|
||||
let nums = [1, 2, 3];
|
||||
|
||||
for num in nums.iter() {
|
||||
println!("{}", num);
|
||||
|
@ -239,12 +239,12 @@ These two basic iterators should serve you well. There are some more
|
|||
advanced iterators, including ones that are infinite. Like `count`:
|
||||
|
||||
```{rust}
|
||||
std::iter::count(1i, 5i);
|
||||
std::iter::count(1, 5);
|
||||
```
|
||||
|
||||
This iterator counts up from one, adding five each time. It will give
|
||||
you a new integer every time, forever (well, technically, until it reaches the
|
||||
maximum number representable by an `int`). But since iterators are lazy,
|
||||
maximum number representable by an `i32`). But since iterators are lazy,
|
||||
that's okay! You probably don't want to use `collect()` on it, though...
|
||||
|
||||
That's enough about iterators. Iterator adapters are the last concept
|
||||
|
@ -256,7 +256,7 @@ we need to talk about with regards to iterators. Let's get to it!
|
|||
a new iterator. The simplest one is called `map`:
|
||||
|
||||
```{rust,ignore}
|
||||
range(1i, 100i).map(|x| x + 1i);
|
||||
range(1, 100).map(|x| x + 1);
|
||||
```
|
||||
|
||||
`map` is called upon another iterator, and produces a new iterator where each
|
||||
|
@ -267,7 +267,7 @@ compile the example, you'll get a warning:
|
|||
```{notrust,ignore}
|
||||
warning: unused result which must be used: iterator adaptors are lazy and
|
||||
do nothing unless consumed, #[warn(unused_must_use)] on by default
|
||||
range(1i, 100i).map(|x| x + 1i);
|
||||
range(1, 100).map(|x| x + 1);
|
||||
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
|
@ -275,7 +275,7 @@ Laziness strikes again! That closure will never execute. This example
|
|||
doesn't print any numbers:
|
||||
|
||||
```{rust,ignore}
|
||||
range(1i, 100i).map(|x| println!("{}", x));
|
||||
range(1, 100).map(|x| println!("{}", x));
|
||||
```
|
||||
|
||||
If you are trying to execute a closure on an iterator for its side effects,
|
||||
|
@ -287,7 +287,7 @@ has no side effect on the original iterator. Let's try it out with our infinite
|
|||
iterator from before, `count()`:
|
||||
|
||||
```{rust}
|
||||
for i in std::iter::count(1i, 5i).take(5) {
|
||||
for i in std::iter::count(1, 5).take(5) {
|
||||
println!("{}", i);
|
||||
}
|
||||
```
|
||||
|
@ -307,7 +307,7 @@ returns `true` or `false`. The new iterator `filter()` produces
|
|||
only the elements that that closure returns `true` for:
|
||||
|
||||
```{rust}
|
||||
for i in range(1i, 100i).filter(|&x| x % 2 == 0) {
|
||||
for i in range(1, 100).filter(|&x| x % 2 == 0) {
|
||||
println!("{}", i);
|
||||
}
|
||||
```
|
||||
|
@ -322,11 +322,11 @@ You can chain all three things together: start with an iterator, adapt it
|
|||
a few times, and then consume the result. Check it out:
|
||||
|
||||
```{rust}
|
||||
range(1i, 1000i)
|
||||
range(1, 1000)
|
||||
.filter(|&x| x % 2 == 0)
|
||||
.filter(|&x| x % 3 == 0)
|
||||
.take(5)
|
||||
.collect::<Vec<int>>();
|
||||
.collect::<Vec<i32>>();
|
||||
```
|
||||
|
||||
This will give you a vector containing `6`, `12`, `18`, `24`, and `30`.
|
||||
|
|
|
@ -54,7 +54,7 @@ The other kind of looping construct in Rust is the `while` loop. It looks like
|
|||
this:
|
||||
|
||||
```{rust}
|
||||
let mut x = 5u32; // mut x: u32
|
||||
let mut x = 5; // mut x: u32
|
||||
let mut done = false; // mut done: bool
|
||||
|
||||
while !done {
|
||||
|
@ -91,7 +91,7 @@ can do with safety and code generation, so you should always prefer
|
|||
Let's take a look at that `while` loop we had earlier:
|
||||
|
||||
```{rust}
|
||||
let mut x = 5u32;
|
||||
let mut x = 5;
|
||||
let mut done = false;
|
||||
|
||||
while !done {
|
||||
|
@ -108,7 +108,7 @@ modifying iteration: `break` and `continue`.
|
|||
In this case, we can write the loop in a better way with `break`:
|
||||
|
||||
```{rust}
|
||||
let mut x = 5u32;
|
||||
let mut x = 5;
|
||||
|
||||
loop {
|
||||
x += x - 3;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% The Rust Macros Guide
|
||||
% Macros
|
||||
|
||||
# Introduction
|
||||
|
||||
|
@ -11,8 +11,8 @@ which both pattern-match on their input and both return early in one case,
|
|||
doing nothing otherwise:
|
||||
|
||||
~~~~
|
||||
# enum T { SpecialA(uint), SpecialB(uint) }
|
||||
# fn f() -> uint {
|
||||
# enum T { SpecialA(u32), SpecialB(u32) }
|
||||
# fn f() -> u32 {
|
||||
# let input_1 = T::SpecialA(0);
|
||||
# let input_2 = T::SpecialA(0);
|
||||
match input_1 {
|
||||
|
@ -24,7 +24,7 @@ match input_2 {
|
|||
T::SpecialB(x) => { return x; }
|
||||
_ => {}
|
||||
}
|
||||
# return 0u;
|
||||
# return 0;
|
||||
# }
|
||||
~~~~
|
||||
|
||||
|
@ -37,8 +37,8 @@ lightweight custom syntax extensions, themselves defined using the
|
|||
the pattern in the above code:
|
||||
|
||||
~~~~
|
||||
# enum T { SpecialA(uint), SpecialB(uint) }
|
||||
# fn f() -> uint {
|
||||
# enum T { SpecialA(u32), SpecialB(u32) }
|
||||
# fn f() -> u32 {
|
||||
# let input_1 = T::SpecialA(0);
|
||||
# let input_2 = T::SpecialA(0);
|
||||
macro_rules! early_return {
|
||||
|
@ -165,8 +165,8 @@ separator token (a comma-separated list could be written `$(...),*`), and `+`
|
|||
instead of `*` to mean "at least one".
|
||||
|
||||
~~~~
|
||||
# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)}
|
||||
# fn f() -> uint {
|
||||
# enum T { SpecialA(u32), SpecialB(u32), SpecialC(u32), SpecialD(u32) }
|
||||
# fn f() -> u32 {
|
||||
# let input_1 = T::SpecialA(0);
|
||||
# let input_2 = T::SpecialA(0);
|
||||
macro_rules! early_return {
|
||||
|
@ -226,10 +226,10 @@ solves the problem.
|
|||
Now consider code like the following:
|
||||
|
||||
~~~~
|
||||
# enum T1 { Good1(T2, uint), Bad1}
|
||||
# enum T1 { Good1(T2, u32), Bad1}
|
||||
# struct T2 { body: T3 }
|
||||
# enum T3 { Good2(uint), Bad2}
|
||||
# fn f(x: T1) -> uint {
|
||||
# enum T3 { Good2(u32), Bad2}
|
||||
# fn f(x: T1) -> u32 {
|
||||
match x {
|
||||
T1::Good1(g1, val) => {
|
||||
match g1.body {
|
||||
|
@ -273,10 +273,10 @@ macro_rules! biased_match {
|
|||
)
|
||||
}
|
||||
|
||||
# enum T1 { Good1(T2, uint), Bad1}
|
||||
# enum T1 { Good1(T2, u32), Bad1}
|
||||
# struct T2 { body: T3 }
|
||||
# enum T3 { Good2(uint), Bad2}
|
||||
# fn f(x: T1) -> uint {
|
||||
# enum T3 { Good2(u32), Bad2}
|
||||
# fn f(x: T1) -> u32 {
|
||||
biased_match!((x) -> (T1::Good1(g1, val)) else { return 0 };
|
||||
binds g1, val );
|
||||
biased_match!((g1.body) -> (T3::Good2(result) )
|
||||
|
@ -383,10 +383,10 @@ macro_rules! biased_match {
|
|||
}
|
||||
|
||||
|
||||
# enum T1 { Good1(T2, uint), Bad1}
|
||||
# enum T1 { Good1(T2, u32), Bad1}
|
||||
# struct T2 { body: T3 }
|
||||
# enum T3 { Good2(uint), Bad2}
|
||||
# fn f(x: T1) -> uint {
|
||||
# enum T3 { Good2(u32), Bad2}
|
||||
# fn f(x: T1) -> u32 {
|
||||
biased_match!(
|
||||
(x) -> (T1::Good1(g1, val)) else { return 0 };
|
||||
(g1.body) -> (T3::Good2(result) ) else { panic!("Didn't get Good2") };
|
||||
|
@ -528,7 +528,7 @@ A further difficulty occurs when a macro is used in multiple crates. Say that
|
|||
`mylib` defines
|
||||
|
||||
```rust
|
||||
pub fn increment(x: uint) -> uint {
|
||||
pub fn increment(x: u32) -> u32 {
|
||||
x + 1
|
||||
}
|
||||
|
||||
|
|
|
@ -84,9 +84,9 @@ fn main() {
|
|||
let y = 10;
|
||||
|
||||
match cmp(x, y) {
|
||||
Ordering::Less => println!("less"),
|
||||
Ordering::Less => println!("less"),
|
||||
Ordering::Greater => println!("greater"),
|
||||
Ordering::Equal => println!("equal"),
|
||||
Ordering::Equal => println!("equal"),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -112,12 +112,12 @@ fn main() {
|
|||
|
||||
match x {
|
||||
OptionalInt::Value(n) => println!("x is {}", n),
|
||||
OptionalInt::Missing => println!("x is missing!"),
|
||||
OptionalInt::Missing => println!("x is missing!"),
|
||||
}
|
||||
|
||||
match y {
|
||||
OptionalInt::Value(n) => println!("y is {}", n),
|
||||
OptionalInt::Missing => println!("y is missing!"),
|
||||
OptionalInt::Missing => println!("y is missing!"),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -146,9 +146,9 @@ fn main() {
|
|||
let y = 10;
|
||||
|
||||
println!("{}", match cmp(x, y) {
|
||||
Ordering::Less => "less",
|
||||
Ordering::Less => "less",
|
||||
Ordering::Greater => "greater",
|
||||
Ordering::Equal => "equal",
|
||||
Ordering::Equal => "equal",
|
||||
});
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% The Rust Ownership Guide
|
||||
% Ownership
|
||||
|
||||
This guide presents Rust's ownership system. This is one of Rust's most unique
|
||||
and compelling features, with which Rust developers should become quite
|
||||
|
@ -418,7 +418,7 @@ struct Wheel {
|
|||
fn main() {
|
||||
let car = Car { name: "DeLorean".to_string() };
|
||||
|
||||
for _ in range(0u, 4) {
|
||||
for _ in range(0, 4) {
|
||||
Wheel { size: 360, owner: car };
|
||||
}
|
||||
}
|
||||
|
@ -456,7 +456,7 @@ fn main() {
|
|||
|
||||
let car_owner = Rc::new(car);
|
||||
|
||||
for _ in range(0u, 4) {
|
||||
for _ in range(0, 4) {
|
||||
Wheel { size: 360, owner: car_owner.clone() };
|
||||
}
|
||||
}
|
||||
|
@ -517,31 +517,31 @@ Here are some examples of functions with elided lifetimes, and the version of
|
|||
what the elided lifetimes are expand to:
|
||||
|
||||
```{rust,ignore}
|
||||
fn print(s: &str); // elided
|
||||
fn print<'a>(s: &'a str); // expanded
|
||||
fn print(s: &str); // elided
|
||||
fn print<'a>(s: &'a str); // expanded
|
||||
|
||||
fn debug(lvl: u32, s: &str); // elided
|
||||
fn debug<'a>(lvl: u32, s: &'a str); // expanded
|
||||
fn debug(lvl: u32, s: &str); // elided
|
||||
fn debug<'a>(lvl: u32, s: &'a str); // expanded
|
||||
|
||||
// In the preceeding example, `lvl` doesn't need a lifetime because it's not a
|
||||
// reference (`&`). Only things relating to references (such as a `struct`
|
||||
// which contains a reference) need lifetimes.
|
||||
|
||||
fn substr(s: &str, until: u32) -> &str; // elided
|
||||
fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded
|
||||
fn substr(s: &str, until: u32) -> &str; // elided
|
||||
fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded
|
||||
|
||||
fn get_str() -> &str; // ILLEGAL, no inputs
|
||||
fn get_str() -> &str; // ILLEGAL, no inputs
|
||||
|
||||
fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
|
||||
fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
|
||||
|
||||
fn get_mut(&mut self) -> &mut T; // elided
|
||||
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
|
||||
fn get_mut(&mut self) -> &mut T; // elided
|
||||
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
|
||||
|
||||
fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
|
||||
fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
|
||||
fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
|
||||
|
||||
fn new(buf: &mut [u8]) -> BufWriter; // elided
|
||||
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
|
||||
fn new(buf: &mut [u8]) -> BufWriter; // elided
|
||||
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
|
||||
```
|
||||
|
||||
# Related Resources
|
||||
|
|
|
@ -8,7 +8,7 @@ A quick refresher: you can match against literals directly, and `_` acts as an
|
|||
*any* case:
|
||||
|
||||
```{rust}
|
||||
let x = 1i;
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
1 => println!("one"),
|
||||
|
@ -21,7 +21,7 @@ match x {
|
|||
You can match multiple patterns with `|`:
|
||||
|
||||
```{rust}
|
||||
let x = 1i;
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
1 | 2 => println!("one or two"),
|
||||
|
@ -33,7 +33,7 @@ match x {
|
|||
You can match a range of values with `...`:
|
||||
|
||||
```{rust}
|
||||
let x = 1i;
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
1 ... 5 => println!("one through five"),
|
||||
|
@ -47,7 +47,7 @@ If you're matching multiple things, via a `|` or a `...`, you can bind
|
|||
the value to a name with `@`:
|
||||
|
||||
```{rust}
|
||||
let x = 1i;
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
e @ 1 ... 5 => println!("got a range element {}", e),
|
||||
|
@ -60,15 +60,15 @@ ignore the value and type in the variant:
|
|||
|
||||
```{rust}
|
||||
enum OptionalInt {
|
||||
Value(int),
|
||||
Value(i32),
|
||||
Missing,
|
||||
}
|
||||
|
||||
let x = OptionalInt::Value(5i);
|
||||
let x = OptionalInt::Value(5);
|
||||
|
||||
match x {
|
||||
OptionalInt::Value(..) => println!("Got an int!"),
|
||||
OptionalInt::Missing => println!("No such luck."),
|
||||
OptionalInt::Missing => println!("No such luck."),
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -76,16 +76,16 @@ You can introduce *match guards* with `if`:
|
|||
|
||||
```{rust}
|
||||
enum OptionalInt {
|
||||
Value(int),
|
||||
Value(i32),
|
||||
Missing,
|
||||
}
|
||||
|
||||
let x = OptionalInt::Value(5i);
|
||||
let x = OptionalInt::Value(5);
|
||||
|
||||
match x {
|
||||
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
|
||||
OptionalInt::Value(..) => println!("Got an int!"),
|
||||
OptionalInt::Missing => println!("No such luck."),
|
||||
OptionalInt::Missing => println!("No such luck."),
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -93,33 +93,33 @@ If you're matching on a pointer, you can use the same syntax as you declared it
|
|||
with. First, `&`:
|
||||
|
||||
```{rust}
|
||||
let x = &5i;
|
||||
let x = &5;
|
||||
|
||||
match x {
|
||||
&val => println!("Got a value: {}", val),
|
||||
}
|
||||
```
|
||||
|
||||
Here, the `val` inside the `match` has type `int`. In other words, the left-hand
|
||||
side of the pattern destructures the value. If we have `&5i`, then in `&val`, `val`
|
||||
would be `5i`.
|
||||
Here, the `val` inside the `match` has type `i32`. In other words, the left-hand
|
||||
side of the pattern destructures the value. If we have `&5`, then in `&val`, `val`
|
||||
would be `5`.
|
||||
|
||||
If you want to get a reference, use the `ref` keyword:
|
||||
|
||||
```{rust}
|
||||
let x = 5i;
|
||||
let x = 5;
|
||||
|
||||
match x {
|
||||
ref r => println!("Got a reference to {}", r),
|
||||
}
|
||||
```
|
||||
|
||||
Here, the `r` inside the `match` has the type `&int`. In other words, the `ref`
|
||||
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
|
||||
keyword _creates_ a reference, for use in the pattern. If you need a mutable
|
||||
reference, `ref mut` will work in the same way:
|
||||
|
||||
```{rust}
|
||||
let mut x = 5i;
|
||||
let mut x = 5;
|
||||
|
||||
match x {
|
||||
ref mut mr => println!("Got a mutable reference to {}", mr),
|
||||
|
@ -131,11 +131,11 @@ If you have a struct, you can destructure it inside of a pattern:
|
|||
```{rust}
|
||||
# #![allow(non_shorthand_field_patterns)]
|
||||
struct Point {
|
||||
x: int,
|
||||
y: int,
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
let origin = Point { x: 0i, y: 0i };
|
||||
let origin = Point { x: 0, y: 0 };
|
||||
|
||||
match origin {
|
||||
Point { x: x, y: y } => println!("({},{})", x, y),
|
||||
|
@ -147,11 +147,11 @@ If we only care about some of the values, we don't have to give them all names:
|
|||
```{rust}
|
||||
# #![allow(non_shorthand_field_patterns)]
|
||||
struct Point {
|
||||
x: int,
|
||||
y: int,
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
let origin = Point { x: 0i, y: 0i };
|
||||
let origin = Point { x: 0, y: 0 };
|
||||
|
||||
match origin {
|
||||
Point { x: x, .. } => println!("x is {}", x),
|
||||
|
@ -163,11 +163,11 @@ You can do this kind of match on any member, not just the first:
|
|||
```{rust}
|
||||
# #![allow(non_shorthand_field_patterns)]
|
||||
struct Point {
|
||||
x: int,
|
||||
y: int,
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
let origin = Point { x: 0i, y: 0i };
|
||||
let origin = Point { x: 0, y: 0 };
|
||||
|
||||
match origin {
|
||||
Point { y: y, .. } => println!("y is {}", y),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% The Rust Compiler Plugins Guide
|
||||
% Compiler Plugins
|
||||
|
||||
<div class="unstable-feature">
|
||||
|
||||
|
@ -68,7 +68,7 @@ use rustc::plugin::Registry;
|
|||
fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
|
||||
-> Box<MacResult + 'static> {
|
||||
|
||||
static NUMERALS: &'static [(&'static str, uint)] = &[
|
||||
static NUMERALS: &'static [(&'static str, u32)] = &[
|
||||
("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
|
||||
("C", 100), ("XC", 90), ("L", 50), ("XL", 40),
|
||||
("X", 10), ("IX", 9), ("V", 5), ("IV", 4),
|
||||
|
@ -83,7 +83,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
|
|||
};
|
||||
|
||||
let mut text = text.as_slice();
|
||||
let mut total = 0u;
|
||||
let mut total = 0;
|
||||
while !text.is_empty() {
|
||||
match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
|
||||
Some(&(rn, val)) => {
|
||||
|
@ -118,7 +118,7 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
The advantages over a simple `fn(&str) -> uint` are:
|
||||
The advantages over a simple `fn(&str) -> u32` are:
|
||||
|
||||
* The (arbitrarily complex) conversion is done at compile time.
|
||||
* Input validation is also performed at compile time.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% The Rust Pointer Guide
|
||||
% Pointers
|
||||
|
||||
Rust's pointers are one of its more unique and compelling features. Pointers
|
||||
are also one of the more confusing topics for newcomers to Rust. They can also
|
||||
|
@ -28,9 +28,10 @@ question](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-
|
|||
as the rest of this guide assumes you know the difference.) Like this:
|
||||
|
||||
```{rust}
|
||||
let x = 5i;
|
||||
let y = 8i;
|
||||
let x = 5;
|
||||
let y = 8;
|
||||
```
|
||||
|
||||
| location | value |
|
||||
|----------|-------|
|
||||
| 0xd3e030 | 5 |
|
||||
|
@ -46,10 +47,11 @@ Let's introduce a pointer. In some languages, there is just one type of
|
|||
*reference*, which is the simplest kind of pointer.
|
||||
|
||||
```{rust}
|
||||
let x = 5i;
|
||||
let y = 8i;
|
||||
let x = 5;
|
||||
let y = 8;
|
||||
let z = &y;
|
||||
```
|
||||
|
||||
|location | value |
|
||||
|-------- |----------|
|
||||
|0xd3e030 | 5 |
|
||||
|
@ -58,12 +60,12 @@ let z = &y;
|
|||
|
||||
See the difference? Rather than contain a value, the value of a pointer is a
|
||||
location in memory. In this case, the location of `y`. `x` and `y` have the
|
||||
type `int`, but `z` has the type `&int`. We can print this location using the
|
||||
type `i32`, but `z` has the type `&i32`. We can print this location using the
|
||||
`{:p}` format string:
|
||||
|
||||
```{rust}
|
||||
let x = 5i;
|
||||
let y = 8i;
|
||||
let x = 5;
|
||||
let y = 8;
|
||||
let z = &y;
|
||||
|
||||
println!("{:p}", z);
|
||||
|
@ -71,12 +73,12 @@ println!("{:p}", z);
|
|||
|
||||
This would print `0xd3e028`, with our fictional memory addresses.
|
||||
|
||||
Because `int` and `&int` are different types, we can't, for example, add them
|
||||
Because `i32` and `&i32` are different types, we can't, for example, add them
|
||||
together:
|
||||
|
||||
```{rust,ignore}
|
||||
let x = 5i;
|
||||
let y = 8i;
|
||||
let x = 5;
|
||||
let y = 8;
|
||||
let z = &y;
|
||||
|
||||
println!("{}", x + z);
|
||||
|
@ -85,7 +87,7 @@ println!("{}", x + z);
|
|||
This gives us an error:
|
||||
|
||||
```text
|
||||
hello.rs:6:24: 6:25 error: mismatched types: expected `int` but found `&int` (expected int but found &-ptr)
|
||||
hello.rs:6:24: 6:25 error: mismatched types: expected `i32` but found `&i32` (expected i32 but found &-ptr)
|
||||
hello.rs:6 println!("{}", x + z);
|
||||
^
|
||||
```
|
||||
|
@ -95,8 +97,8 @@ pointer means accessing the value at the location stored in the pointer. This
|
|||
will work:
|
||||
|
||||
```{rust}
|
||||
let x = 5i;
|
||||
let y = 8i;
|
||||
let x = 5;
|
||||
let y = 8;
|
||||
let z = &y;
|
||||
|
||||
println!("{}", x + *z);
|
||||
|
@ -153,7 +155,7 @@ So what do pointers have to do with this? Well, since pointers point to a
|
|||
location in memory...
|
||||
|
||||
```text
|
||||
func foo(&int x) {
|
||||
func foo(&i32 x) {
|
||||
*x = 5
|
||||
}
|
||||
|
||||
|
@ -252,7 +254,7 @@ The most basic type of pointer that Rust has is called a *reference*. Rust
|
|||
references look like this:
|
||||
|
||||
```{rust}
|
||||
let x = 5i;
|
||||
let x = 5;
|
||||
let y = &x;
|
||||
|
||||
println!("{}", *y);
|
||||
|
@ -269,18 +271,18 @@ referent, because `println!` will automatically dereference it for us.
|
|||
Here's a function that takes a reference:
|
||||
|
||||
```{rust}
|
||||
fn succ(x: &int) -> int { *x + 1 }
|
||||
fn succ(x: &i32) -> i32 { *x + 1 }
|
||||
```
|
||||
|
||||
You can also use `&` as an operator to create a reference, so we can
|
||||
call this function in two different ways:
|
||||
|
||||
```{rust}
|
||||
fn succ(x: &int) -> int { *x + 1 }
|
||||
fn succ(x: &i32) -> i32 { *x + 1 }
|
||||
|
||||
fn main() {
|
||||
|
||||
let x = 5i;
|
||||
let x = 5;
|
||||
let y = &x;
|
||||
|
||||
println!("{}", succ(y));
|
||||
|
@ -294,13 +296,13 @@ Of course, if this were real code, we wouldn't bother with the reference, and
|
|||
just write:
|
||||
|
||||
```{rust}
|
||||
fn succ(x: int) -> int { x + 1 }
|
||||
fn succ(x: i32) -> i32 { x + 1 }
|
||||
```
|
||||
|
||||
References are immutable by default:
|
||||
|
||||
```{rust,ignore}
|
||||
let x = 5i;
|
||||
let x = 5;
|
||||
let y = &x;
|
||||
|
||||
*y = 5; // error: cannot assign to immutable dereference of `&`-pointer `*y`
|
||||
|
@ -310,21 +312,21 @@ They can be made mutable with `mut`, but only if its referent is also mutable.
|
|||
This works:
|
||||
|
||||
```{rust}
|
||||
let mut x = 5i;
|
||||
let mut x = 5;
|
||||
let y = &mut x;
|
||||
```
|
||||
|
||||
This does not:
|
||||
|
||||
```{rust,ignore}
|
||||
let x = 5i;
|
||||
let x = 5;
|
||||
let y = &mut x; // error: cannot borrow immutable local variable `x` as mutable
|
||||
```
|
||||
|
||||
Immutable pointers are allowed to alias:
|
||||
|
||||
```{rust}
|
||||
let x = 5i;
|
||||
let x = 5;
|
||||
let y = &x;
|
||||
let z = &x;
|
||||
```
|
||||
|
@ -332,7 +334,7 @@ let z = &x;
|
|||
Mutable ones, however, are not:
|
||||
|
||||
```{rust,ignore}
|
||||
let mut x = 5i;
|
||||
let mut x = 5;
|
||||
let y = &mut x;
|
||||
let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time
|
||||
```
|
||||
|
@ -359,7 +361,7 @@ duration a *lifetime*. Let's try a more complex example:
|
|||
|
||||
```{rust}
|
||||
fn main() {
|
||||
let x = &mut 5i;
|
||||
let x = &mut 5;
|
||||
|
||||
if *x < 10 {
|
||||
let y = &x;
|
||||
|
@ -380,7 +382,7 @@ mutated, and therefore, lets us pass. This wouldn't work:
|
|||
|
||||
```{rust,ignore}
|
||||
fn main() {
|
||||
let x = &mut 5i;
|
||||
let x = &mut 5;
|
||||
|
||||
if *x < 10 {
|
||||
let y = &x;
|
||||
|
@ -425,13 +427,13 @@ References just borrow ownership, which is more polite if you don't need the
|
|||
ownership. In other words, prefer:
|
||||
|
||||
```{rust}
|
||||
fn succ(x: &int) -> int { *x + 1 }
|
||||
fn succ(x: &i32) -> i32 { *x + 1 }
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```{rust}
|
||||
fn succ(x: Box<int>) -> int { *x + 1 }
|
||||
fn succ(x: Box<i32>) -> i32 { *x + 1 }
|
||||
```
|
||||
|
||||
As a corollary to that rule, references allow you to accept a wide variety of
|
||||
|
@ -439,7 +441,7 @@ other pointers, and so are useful so that you don't have to write a number
|
|||
of variants per pointer. In other words, prefer:
|
||||
|
||||
```{rust}
|
||||
fn succ(x: &int) -> int { *x + 1 }
|
||||
fn succ(x: &i32) -> i32 { *x + 1 }
|
||||
```
|
||||
|
||||
to
|
||||
|
@ -447,9 +449,9 @@ to
|
|||
```{rust}
|
||||
use std::rc::Rc;
|
||||
|
||||
fn box_succ(x: Box<int>) -> int { *x + 1 }
|
||||
fn box_succ(x: Box<i32>) -> i32 { *x + 1 }
|
||||
|
||||
fn rc_succ(x: Rc<int>) -> int { *x + 1 }
|
||||
fn rc_succ(x: Rc<i32>) -> i32 { *x + 1 }
|
||||
```
|
||||
|
||||
Note that the caller of your function will have to modify their calls slightly:
|
||||
|
@ -457,11 +459,11 @@ Note that the caller of your function will have to modify their calls slightly:
|
|||
```{rust}
|
||||
use std::rc::Rc;
|
||||
|
||||
fn succ(x: &int) -> int { *x + 1 }
|
||||
fn succ(x: &i32) -> i32 { *x + 1 }
|
||||
|
||||
let ref_x = &5i;
|
||||
let box_x = Box::new(5i);
|
||||
let rc_x = Rc::new(5i);
|
||||
let ref_x = &5;
|
||||
let box_x = Box::new(5);
|
||||
let rc_x = Rc::new(5);
|
||||
|
||||
succ(ref_x);
|
||||
succ(&*box_x);
|
||||
|
@ -477,7 +479,7 @@ those contents.
|
|||
heap allocation in Rust. Creating a box looks like this:
|
||||
|
||||
```{rust}
|
||||
let x = Box::new(5i);
|
||||
let x = Box::new(5);
|
||||
```
|
||||
|
||||
Boxes are heap allocated and they are deallocated automatically by Rust when
|
||||
|
@ -485,7 +487,7 @@ they go out of scope:
|
|||
|
||||
```{rust}
|
||||
{
|
||||
let x = Box::new(5i);
|
||||
let x = Box::new(5);
|
||||
|
||||
// stuff happens
|
||||
|
||||
|
@ -505,7 +507,7 @@ boxes, though. As a rough approximation, you can treat this Rust code:
|
|||
|
||||
```{rust}
|
||||
{
|
||||
let x = Box::new(5i);
|
||||
let x = Box::new(5);
|
||||
|
||||
// stuff happens
|
||||
}
|
||||
|
@ -544,12 +546,12 @@ for more detail on how lifetimes work.
|
|||
Using boxes and references together is very common. For example:
|
||||
|
||||
```{rust}
|
||||
fn add_one(x: &int) -> int {
|
||||
fn add_one(x: &i32) -> i32 {
|
||||
*x + 1
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Box::new(5i);
|
||||
let x = Box::new(5);
|
||||
|
||||
println!("{}", add_one(&*x));
|
||||
}
|
||||
|
@ -561,12 +563,12 @@ function, and since it's only reading the value, allows it.
|
|||
We can borrow `x` multiple times, as long as it's not simultaneous:
|
||||
|
||||
```{rust}
|
||||
fn add_one(x: &int) -> int {
|
||||
fn add_one(x: &i32) -> i32 {
|
||||
*x + 1
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Box::new(5i);
|
||||
let x = Box::new(5);
|
||||
|
||||
println!("{}", add_one(&*x));
|
||||
println!("{}", add_one(&*x));
|
||||
|
@ -577,12 +579,12 @@ fn main() {
|
|||
Or as long as it's not a mutable borrow. This will error:
|
||||
|
||||
```{rust,ignore}
|
||||
fn add_one(x: &mut int) -> int {
|
||||
fn add_one(x: &mut i32) -> i32 {
|
||||
*x + 1
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Box::new(5i);
|
||||
let x = Box::new(5);
|
||||
|
||||
println!("{}", add_one(&*x)); // error: cannot borrow immutable dereference
|
||||
// of `&`-pointer as mutable
|
||||
|
@ -610,7 +612,7 @@ enum List<T> {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let list: List<int> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
|
||||
let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
|
||||
println!("{:?}", list);
|
||||
}
|
||||
```
|
||||
|
@ -659,10 +661,10 @@ so as to avoid copying a large data structure. For example:
|
|||
|
||||
```{rust}
|
||||
struct BigStruct {
|
||||
one: int,
|
||||
two: int,
|
||||
one: i32,
|
||||
two: i32,
|
||||
// etc
|
||||
one_hundred: int,
|
||||
one_hundred: i32,
|
||||
}
|
||||
|
||||
fn foo(x: Box<BigStruct>) -> Box<BigStruct> {
|
||||
|
@ -687,10 +689,10 @@ This is an antipattern in Rust. Instead, write this:
|
|||
|
||||
```{rust}
|
||||
struct BigStruct {
|
||||
one: int,
|
||||
two: int,
|
||||
one: i32,
|
||||
two: i32,
|
||||
// etc
|
||||
one_hundred: int,
|
||||
one_hundred: i32,
|
||||
}
|
||||
|
||||
fn foo(x: Box<BigStruct>) -> BigStruct {
|
||||
|
|
|
@ -83,12 +83,12 @@ fn main() {
|
|||
|
||||
match x {
|
||||
OptionalInt::Value(n) => println!("x is {}", n),
|
||||
OptionalInt::Missing => println!("x is missing!"),
|
||||
OptionalInt::Missing => println!("x is missing!"),
|
||||
}
|
||||
|
||||
match y {
|
||||
OptionalInt::Value(n) => println!("y is {}", n),
|
||||
OptionalInt::Missing => println!("y is missing!"),
|
||||
OptionalInt::Missing => println!("y is missing!"),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -141,11 +141,11 @@ use std::io;
|
|||
fn main() {
|
||||
println!("Type something!");
|
||||
|
||||
// here, we'll show the types at each step
|
||||
// here, we'll show the types at each step
|
||||
|
||||
let input = io::stdin() // std::io::stdio::StdinReader
|
||||
.read_line() // IoResult<String>
|
||||
.ok() // Option<String>
|
||||
let input = io::stdin() // std::io::stdio::StdinReader
|
||||
.read_line() // IoResult<String>
|
||||
.ok() // Option<String>
|
||||
.expect("Failed to read line"); // String
|
||||
|
||||
println!("{}", input);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% The Rust Testing Guide
|
||||
% Testing
|
||||
|
||||
> Program testing can be a very effective way to show the presence of bugs, but
|
||||
> it is hopelessly inadequate for showing their absence.
|
||||
|
@ -512,7 +512,7 @@ use test::Bencher;
|
|||
#[bench]
|
||||
fn bench_xor_1000_ints(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
range(0u, 1000).fold(0, |old, new| old ^ new);
|
||||
range(0, 1000).fold(0, |old, new| old ^ new);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
@ -537,7 +537,7 @@ computation entirely. This could be done for the example above by adjusting the
|
|||
# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
|
||||
b.iter(|| {
|
||||
// note lack of `;` (could also use an explicit `return`).
|
||||
range(0u, 1000).fold(0, |old, new| old ^ new)
|
||||
range(0, 1000).fold(0, |old, new| old ^ new)
|
||||
});
|
||||
```
|
||||
|
||||
|
|
|
@ -51,13 +51,15 @@ closure is limited to capturing `Send`-able data from its environment
|
|||
ensures that `spawn` can safely move the entire closure and all its
|
||||
associated state into an entirely different thread for execution.
|
||||
|
||||
```{rust,ignore}
|
||||
# use std::thread::spawn;
|
||||
# fn generate_thread_number() -> int { 0 }
|
||||
```rust
|
||||
use std::thread::Thread;
|
||||
|
||||
fn generate_thread_number() -> i32 { 4 } // a very simple generation
|
||||
|
||||
// Generate some state locally
|
||||
let child_thread_number = generate_thread_number();
|
||||
|
||||
spawn(move || {
|
||||
Thread::spawn(move || {
|
||||
// Capture it in the remote thread. The `move` keyword indicates
|
||||
// that this closure should move `child_thread_number` into its
|
||||
// environment, rather than capturing a reference into the
|
||||
|
@ -77,20 +79,22 @@ The simplest way to create a channel is to use the `channel` function to create
|
|||
of a channel, and a *receiver* is the receiving endpoint. Consider the following
|
||||
example of calculating two results concurrently:
|
||||
|
||||
```{rust,ignore}
|
||||
# use std::thread::spawn;
|
||||
```rust
|
||||
use std::thread::Thread;
|
||||
use std::sync::mpsc;
|
||||
|
||||
let (tx, rx): (Sender<int>, Receiver<int>) = channel();
|
||||
let (tx, rx): (mpsc::Sender<u32>, mpsc::Receiver<u32>) = mpsc::channel();
|
||||
|
||||
spawn(move || {
|
||||
Thread::spawn(move || {
|
||||
let result = some_expensive_computation();
|
||||
tx.send(result);
|
||||
});
|
||||
|
||||
some_other_expensive_computation();
|
||||
let result = rx.recv();
|
||||
# fn some_expensive_computation() -> int { 42 }
|
||||
# fn some_other_expensive_computation() {}
|
||||
|
||||
fn some_expensive_computation() -> u32 { 42 } // very expensive ;)
|
||||
fn some_other_expensive_computation() {} // even more so
|
||||
```
|
||||
|
||||
Let's examine this example in detail. First, the `let` statement creates a
|
||||
|
@ -98,19 +102,21 @@ stream for sending and receiving integers (the left-hand side of the `let`,
|
|||
`(tx, rx)`, is an example of a destructuring let: the pattern separates a tuple
|
||||
into its component parts).
|
||||
|
||||
```{rust,ignore}
|
||||
let (tx, rx): (Sender<int>, Receiver<int>) = channel();
|
||||
```rust
|
||||
# use std::sync::mpsc;
|
||||
let (tx, rx): (mpsc::Sender<u32>, mpsc::Receiver<u32>) = mpsc::channel();
|
||||
```
|
||||
|
||||
The child thread will use the sender to send data to the parent thread, which will
|
||||
wait to receive the data on the receiver. The next statement spawns the child
|
||||
thread.
|
||||
|
||||
```{rust,ignore}
|
||||
# use std::thread::spawn;
|
||||
# fn some_expensive_computation() -> int { 42 }
|
||||
# let (tx, rx) = channel();
|
||||
spawn(move || {
|
||||
```rust
|
||||
# use std::thread::Thread;
|
||||
# use std::sync::mpsc;
|
||||
# fn some_expensive_computation() -> u32 { 42 }
|
||||
# let (tx, rx) = mpsc::channel();
|
||||
Thread::spawn(move || {
|
||||
let result = some_expensive_computation();
|
||||
tx.send(result);
|
||||
});
|
||||
|
@ -125,9 +131,10 @@ computation, then sends the result over the captured channel.
|
|||
Finally, the parent continues with some other expensive computation, then waits
|
||||
for the child's result to arrive on the receiver:
|
||||
|
||||
```{rust,ignore}
|
||||
```rust
|
||||
# use std::sync::mpsc;
|
||||
# fn some_other_expensive_computation() {}
|
||||
# let (tx, rx) = channel::<int>();
|
||||
# let (tx, rx) = mpsc::channel::<u32>();
|
||||
# tx.send(0);
|
||||
some_other_expensive_computation();
|
||||
let result = rx.recv();
|
||||
|
@ -140,8 +147,9 @@ single `Receiver` value. What if our example needed to compute multiple
|
|||
results across a number of threads? The following program is ill-typed:
|
||||
|
||||
```{rust,ignore}
|
||||
# fn some_expensive_computation() -> int { 42 }
|
||||
let (tx, rx) = channel();
|
||||
# use std::sync::mpsc;
|
||||
# fn some_expensive_computation() -> u32 { 42 }
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
spawn(move || {
|
||||
tx.send(some_expensive_computation());
|
||||
|
@ -156,19 +164,22 @@ spawn(move || {
|
|||
|
||||
Instead we can clone the `tx`, which allows for multiple senders.
|
||||
|
||||
```{rust,ignore}
|
||||
let (tx, rx) = channel();
|
||||
```rust
|
||||
use std::thread::Thread;
|
||||
use std::sync::mpsc;
|
||||
|
||||
for init_val in range(0u, 3) {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
for init_val in 0 .. 3 {
|
||||
// Create a new channel handle to distribute to the child thread
|
||||
let child_tx = tx.clone();
|
||||
spawn(move || {
|
||||
Thread::spawn(move || {
|
||||
child_tx.send(some_expensive_computation(init_val));
|
||||
});
|
||||
}
|
||||
|
||||
let result = rx.recv() + rx.recv() + rx.recv();
|
||||
# fn some_expensive_computation(_i: uint) -> int { 42 }
|
||||
let result = rx.recv().unwrap() + rx.recv().unwrap() + rx.recv().unwrap();
|
||||
# fn some_expensive_computation(_i: u32) -> u32 { 42 }
|
||||
```
|
||||
|
||||
Cloning a `Sender` produces a new handle to the same channel, allowing multiple
|
||||
|
@ -181,21 +192,22 @@ Note that the above cloning example is somewhat contrived since you could also
|
|||
simply use three `Sender` pairs, but it serves to illustrate the point. For
|
||||
reference, written with multiple streams, it might look like the example below.
|
||||
|
||||
```{rust,ignore}
|
||||
# use std::thread::spawn;
|
||||
```rust
|
||||
use std::thread::Thread;
|
||||
use std::sync::mpsc;
|
||||
|
||||
// Create a vector of ports, one for each child thread
|
||||
let rxs = Vec::from_fn(3, |init_val| {
|
||||
let (tx, rx) = channel();
|
||||
spawn(move || {
|
||||
let rxs = (0 .. 3).map(|&:init_val| {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
Thread::spawn(move || {
|
||||
tx.send(some_expensive_computation(init_val));
|
||||
});
|
||||
rx
|
||||
});
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Wait on each port, accumulating the results
|
||||
let result = rxs.iter().fold(0, |accum, rx| accum + rx.recv() );
|
||||
# fn some_expensive_computation(_i: uint) -> int { 42 }
|
||||
let result = rxs.iter().fold(0, |&:accum, rx| accum + rx.recv().unwrap() );
|
||||
# fn some_expensive_computation(_i: u32) -> u32 { 42 }
|
||||
```
|
||||
|
||||
## Backgrounding computations: Futures
|
||||
|
@ -212,7 +224,7 @@ use std::sync::Future;
|
|||
# fn main() {
|
||||
# fn make_a_sandwich() {};
|
||||
fn fib(n: u64) -> u64 {
|
||||
// lengthy computation returning an uint
|
||||
// lengthy computation returning an 64
|
||||
12586269025
|
||||
}
|
||||
|
||||
|
@ -237,7 +249,7 @@ computations. The workload will be distributed on the available cores.
|
|||
# #![allow(deprecated)]
|
||||
# use std::num::Float;
|
||||
# use std::sync::Future;
|
||||
fn partial_sum(start: uint) -> f64 {
|
||||
fn partial_sum(start: u64) -> f64 {
|
||||
let mut local_sum = 0f64;
|
||||
for num in range(start*100000, (start+1)*100000) {
|
||||
local_sum += (num as f64 + 1.0).powf(-2.0);
|
||||
|
@ -277,7 +289,7 @@ use std::num::Float;
|
|||
use std::rand;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn pnorm(nums: &[f64], p: uint) -> f64 {
|
||||
fn pnorm(nums: &[f64], p: u64) -> f64 {
|
||||
nums.iter().fold(0.0, |a, b| a + b.powf(p as f64)).powf(1.0 / (p as f64))
|
||||
}
|
||||
|
||||
|
@ -285,7 +297,7 @@ fn main() {
|
|||
let numbers = Vec::from_fn(1000000, |_| rand::random::<f64>());
|
||||
let numbers_arc = Arc::new(numbers);
|
||||
|
||||
for num in range(1u, 10) {
|
||||
for num in range(1, 10) {
|
||||
let thread_numbers = numbers_arc.clone();
|
||||
|
||||
spawn(move || {
|
||||
|
@ -316,7 +328,7 @@ if it were local.
|
|||
```{rust,ignore}
|
||||
# use std::rand;
|
||||
# use std::sync::Arc;
|
||||
# fn pnorm(nums: &[f64], p: uint) -> f64 { 4.0 }
|
||||
# fn pnorm(nums: &[f64], p: u64) -> f64 { 4.0 }
|
||||
# fn main() {
|
||||
# let numbers=Vec::from_fn(1000000, |_| rand::random::<f64>());
|
||||
# let numbers_arc = Arc::new(numbers);
|
||||
|
@ -345,16 +357,16 @@ each other if they panic. The simplest way of handling a panic is with the
|
|||
`try` function, which is similar to `spawn`, but immediately blocks and waits
|
||||
for the child thread to finish. `try` returns a value of type
|
||||
`Result<T, Box<Any + Send>>`. `Result` is an `enum` type with two variants:
|
||||
`Ok` and `Err`. In this case, because the type arguments to `Result` are `int`
|
||||
`Ok` and `Err`. In this case, because the type arguments to `Result` are `i32`
|
||||
and `()`, callers can pattern-match on a result to check whether it's an `Ok`
|
||||
result with an `int` field (representing a successful result) or an `Err` result
|
||||
result with an `i32` field (representing a successful result) or an `Err` result
|
||||
(representing termination with an error).
|
||||
|
||||
```{rust,ignore}
|
||||
# use std::thread::Thread;
|
||||
# fn some_condition() -> bool { false }
|
||||
# fn calculate_result() -> int { 0 }
|
||||
let result: Result<int, Box<std::any::Any + Send>> = Thread::spawn(move || {
|
||||
# fn calculate_result() -> i32 { 0 }
|
||||
let result: Result<i32, Box<std::any::Any + Send>> = Thread::spawn(move || {
|
||||
if some_condition() {
|
||||
calculate_result()
|
||||
} else {
|
||||
|
|
|
@ -145,7 +145,7 @@ 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}
|
||||
print_area(5i);
|
||||
print_area(5);
|
||||
```
|
||||
|
||||
We get a compile-time error:
|
||||
|
@ -156,14 +156,14 @@ 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 `int`:
|
||||
`HasArea` for `i32`:
|
||||
|
||||
```{rust}
|
||||
trait HasArea {
|
||||
fn area(&self) -> f64;
|
||||
}
|
||||
|
||||
impl HasArea for int {
|
||||
impl HasArea for i32 {
|
||||
fn area(&self) -> f64 {
|
||||
println!("this is silly");
|
||||
|
||||
|
@ -171,7 +171,7 @@ impl HasArea for int {
|
|||
}
|
||||
}
|
||||
|
||||
5i.area();
|
||||
5.area();
|
||||
```
|
||||
|
||||
It is considered poor style to implement methods on such primitive types, even
|
||||
|
@ -264,8 +264,8 @@ 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 `int`, because `HasArea` is in our crate. But
|
||||
if we tried to implement `Float`, a trait provided by Rust, for `int`, we could
|
||||
implement the `HasArea` type for `i32`, because `HasArea` is in our crate. 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.
|
||||
|
||||
One last thing about traits: generic functions with a trait bound use
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% Writing Unsafe and Low-Level Code in Rust
|
||||
% Unsafe and Low-Level Code
|
||||
|
||||
# Introduction
|
||||
|
||||
|
@ -95,7 +95,7 @@ offered by the Rust language and libraries. For example, they
|
|||
use-after-free;
|
||||
- are considered sendable (if their contents is considered sendable),
|
||||
so the compiler offers no assistance with ensuring their use is
|
||||
thread-safe; for example, one can concurrently access a `*mut int`
|
||||
thread-safe; for example, one can concurrently access a `*mut i32`
|
||||
from two threads without synchronization.
|
||||
- lack any form of lifetimes, unlike `&`, and so the compiler cannot
|
||||
reason about dangling pointers; and
|
||||
|
@ -265,12 +265,12 @@ impl<T: Send> Drop for Unique<T> {
|
|||
// A comparison between the built-in `Box` and this reimplementation
|
||||
fn main() {
|
||||
{
|
||||
let mut x = Box::new(5i);
|
||||
let mut x = Box::new(5);
|
||||
*x = 10;
|
||||
} // `x` is freed here
|
||||
|
||||
{
|
||||
let mut y = Unique::new(5i);
|
||||
let mut y = Unique::new(5);
|
||||
*y.borrow_mut() = 10;
|
||||
} // `y` is freed here
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ expressions must be mutable lvalues:
|
|||
```
|
||||
# #![feature(asm)]
|
||||
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
fn add(a: int, b: int) -> int {
|
||||
fn add(a: i32, b: i32) -> i32 {
|
||||
let mut c = 0;
|
||||
unsafe {
|
||||
asm!("add $2, $0"
|
||||
|
@ -378,7 +378,7 @@ fn add(a: int, b: int) -> int {
|
|||
c
|
||||
}
|
||||
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
# fn add(a: int, b: int) -> int { a + b }
|
||||
# fn add(a: i32, b: i32) -> i32 { a + b }
|
||||
|
||||
fn main() {
|
||||
assert_eq!(add(3, 14159), 14162)
|
||||
|
@ -454,7 +454,7 @@ extern crate libc;
|
|||
|
||||
// Entry point for this program
|
||||
#[start]
|
||||
fn start(_argc: int, _argv: *const *const u8) -> int {
|
||||
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
0
|
||||
}
|
||||
|
||||
|
@ -480,7 +480,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: *const *const u8) -> int {
|
||||
pub extern fn main(argc: i32, argv: *const *const u8) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
|
@ -552,8 +552,8 @@ pub extern fn dot_product(a: *const u32, a_len: u32,
|
|||
// cannot tell the pointers are valid.
|
||||
let (a_slice, b_slice): (&[u32], &[u32]) = unsafe {
|
||||
mem::transmute((
|
||||
Slice { data: a, len: a_len as uint },
|
||||
Slice { data: b, len: b_len as uint },
|
||||
Slice { data: a, len: a_len as usize },
|
||||
Slice { data: b, len: b_len as usize },
|
||||
))
|
||||
};
|
||||
|
||||
|
@ -567,14 +567,14 @@ pub extern fn dot_product(a: *const u32, a_len: u32,
|
|||
|
||||
#[lang = "panic_fmt"]
|
||||
extern fn panic_fmt(args: &core::fmt::Arguments,
|
||||
file: &str,
|
||||
line: uint) -> ! {
|
||||
file: &str,
|
||||
line: u32) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
|
||||
#[lang = "eh_personality"] extern fn eh_personality() {}
|
||||
# #[start] fn start(argc: int, argv: *const *const u8) -> int { 0 }
|
||||
# #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 }
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
|
@ -628,7 +628,7 @@ via a declaration like
|
|||
extern "rust-intrinsic" {
|
||||
fn transmute<T, U>(x: T) -> U;
|
||||
|
||||
fn offset<T>(dst: *const T, offset: int) -> *const T;
|
||||
fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -665,24 +665,24 @@ extern {
|
|||
pub struct Box<T>(*mut T);
|
||||
|
||||
#[lang="exchange_malloc"]
|
||||
unsafe fn allocate(size: uint, _align: uint) -> *mut u8 {
|
||||
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
|
||||
let p = libc::malloc(size as libc::size_t) as *mut u8;
|
||||
|
||||
// malloc failed
|
||||
if p as uint == 0 {
|
||||
if p as usize == 0 {
|
||||
abort();
|
||||
}
|
||||
|
||||
p
|
||||
}
|
||||
#[lang="exchange_free"]
|
||||
unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
|
||||
unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
|
||||
libc::free(ptr as *mut libc::c_void)
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(argc: int, argv: *const *const u8) -> int {
|
||||
let x = box 1i;
|
||||
fn main(argc: isize, argv: *const *const u8) -> isize {
|
||||
let x = box 1;
|
||||
|
||||
0
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% Variable bindings
|
||||
% Variable Bindings
|
||||
|
||||
The first thing we'll learn about are *variable bindings*. They look like this:
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ static FALSE: bool = false;
|
|||
/// println!("{:?}", bv);
|
||||
/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
|
||||
/// ```
|
||||
#[stable]
|
||||
#[unstable = "RFC 509"]
|
||||
pub struct Bitv {
|
||||
/// Internal representation of the bit vector
|
||||
storage: Vec<u32>,
|
||||
|
@ -1107,7 +1107,7 @@ impl<'a> RandomAccessIterator for Iter<'a> {
|
|||
/// assert!(bv[3]);
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
#[stable]
|
||||
#[unstable = "RFC 509"]
|
||||
pub struct BitvSet {
|
||||
bitv: Bitv,
|
||||
}
|
||||
|
|
|
@ -70,12 +70,12 @@ pub mod string;
|
|||
pub mod vec;
|
||||
pub mod vec_map;
|
||||
|
||||
#[stable]
|
||||
#[unstable = "RFC 509"]
|
||||
pub mod bitv {
|
||||
pub use bit::{Bitv, Iter};
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[unstable = "RFC 509"]
|
||||
pub mod bitv_set {
|
||||
pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference};
|
||||
pub use bit::SetIter as Iter;
|
||||
|
|
|
@ -115,7 +115,6 @@
|
|||
//! }
|
||||
//! # fn calc_span_tree(&self) -> Vec<(uint, uint)> { vec![] }
|
||||
//! }
|
||||
//! # fn main() { }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Mutating implementations of `clone`
|
||||
|
|
|
@ -23,13 +23,11 @@
|
|||
//!
|
||||
//! use std::finally::Finally;
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! (|&mut:| {
|
||||
//! // ...
|
||||
//! }).finally(|| {
|
||||
//! // this code is always run
|
||||
//! })
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![deprecated = "It is unclear if this module is more robust than implementing \
|
||||
|
|
|
@ -39,13 +39,16 @@ macro_rules! panic {
|
|||
/// // the panic message for these assertions is the stringified value of the
|
||||
/// // expression given.
|
||||
/// assert!(true);
|
||||
/// # fn some_computation() -> bool { true }
|
||||
///
|
||||
/// fn some_computation() -> bool { true } // a very simple function
|
||||
///
|
||||
/// assert!(some_computation());
|
||||
///
|
||||
/// // assert with a custom message
|
||||
/// # let x = true;
|
||||
/// let x = true;
|
||||
/// assert!(x, "x wasn't true!");
|
||||
/// # let a = 3i; let b = 27i;
|
||||
///
|
||||
/// let a = 3i; let b = 27i;
|
||||
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
|
@ -108,13 +111,15 @@ macro_rules! assert_eq {
|
|||
/// // the panic message for these assertions is the stringified value of the
|
||||
/// // expression given.
|
||||
/// debug_assert!(true);
|
||||
/// # fn some_expensive_computation() -> bool { true }
|
||||
///
|
||||
/// fn some_expensive_computation() -> bool { true } // a very simple function
|
||||
/// debug_assert!(some_expensive_computation());
|
||||
///
|
||||
/// // assert with a custom message
|
||||
/// # let x = true;
|
||||
/// let x = true;
|
||||
/// debug_assert!(x, "x wasn't true!");
|
||||
/// # let a = 3i; let b = 27i;
|
||||
///
|
||||
/// let a = 3; let b = 27;
|
||||
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
|
|
|
@ -42,6 +42,104 @@ pub trait Sized {
|
|||
}
|
||||
|
||||
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
|
||||
///
|
||||
/// By default, variable bindings have 'move semantics.' In other
|
||||
/// words:
|
||||
///
|
||||
/// ```
|
||||
/// #[derive(Show)]
|
||||
/// struct Foo;
|
||||
///
|
||||
/// let x = Foo;
|
||||
///
|
||||
/// let y = x;
|
||||
///
|
||||
/// // `x` has moved into `y`, and so cannot be used
|
||||
///
|
||||
/// // println!("{:?}", x); // error: use of moved value
|
||||
/// ```
|
||||
///
|
||||
/// However, if a type implements `Copy`, it instead has 'copy semantics':
|
||||
///
|
||||
/// ```
|
||||
/// // we can just derive a `Copy` implementation
|
||||
/// #[derive(Show, Copy)]
|
||||
/// struct Foo;
|
||||
///
|
||||
/// let x = Foo;
|
||||
///
|
||||
/// let y = x;
|
||||
///
|
||||
/// // `y` is a copy of `x`
|
||||
///
|
||||
/// println!("{:?}", x); // A-OK!
|
||||
/// ```
|
||||
///
|
||||
/// It's important to note that in these two examples, the only difference is if you are allowed to
|
||||
/// access `x` after the assignment: a move is also a bitwise copy under the hood.
|
||||
///
|
||||
/// ## When can my type be `Copy`?
|
||||
///
|
||||
/// A type can implement `Copy` if all of its components implement `Copy`. For example, this
|
||||
/// `struct` can be `Copy`:
|
||||
///
|
||||
/// ```
|
||||
/// struct Point {
|
||||
/// x: i32,
|
||||
/// y: i32,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`.
|
||||
///
|
||||
/// ```
|
||||
/// # struct Point;
|
||||
/// struct PointList {
|
||||
/// points: Vec<Point>,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The `PointList` `struct` cannot implement `Copy`, because `Vec<T>` is not `Copy`. If we
|
||||
/// attempt to derive a `Copy` implementation, we'll get an error.
|
||||
///
|
||||
/// ```text
|
||||
/// error: the trait `Copy` may not be implemented for this type; field `points` does not implement
|
||||
/// `Copy`
|
||||
/// ```
|
||||
///
|
||||
/// ## How can I implement `Copy`?
|
||||
///
|
||||
/// There are two ways to implement `Copy` on your type:
|
||||
///
|
||||
/// ```
|
||||
/// #[derive(Copy)]
|
||||
/// struct MyStruct;
|
||||
/// ```
|
||||
///
|
||||
/// and
|
||||
///
|
||||
/// ```
|
||||
/// struct MyStruct;
|
||||
/// impl Copy for MyStruct {}
|
||||
/// ```
|
||||
///
|
||||
/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
|
||||
/// bound on type parameters, which isn't always desired.
|
||||
///
|
||||
/// ## When can my type _not_ be `Copy`?
|
||||
///
|
||||
/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased
|
||||
/// mutable reference, and copying `String` would result in two attempts to free the same buffer.
|
||||
///
|
||||
/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's
|
||||
/// managing some resource besides its own `size_of::<T>()` bytes.
|
||||
///
|
||||
/// ## When should my type be `Copy`?
|
||||
///
|
||||
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
|
||||
/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future,
|
||||
/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking
|
||||
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
|
||||
#[stable]
|
||||
#[lang="copy"]
|
||||
pub trait Copy {
|
||||
|
@ -210,8 +308,7 @@ impl<T: ?Sized> Clone for ContravariantType<T> {
|
|||
/// "interior" mutability:
|
||||
///
|
||||
/// ```
|
||||
/// pub struct Cell<T> { value: T }
|
||||
/// # fn main() {}
|
||||
/// struct Cell<T> { value: T }
|
||||
/// ```
|
||||
///
|
||||
/// The type system would infer that `value` is only read here and
|
||||
|
|
|
@ -830,28 +830,27 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// A trivial implementation of `Index`. When `Foo[Foo]` happens, it ends up
|
||||
/// A trivial implementation of `Index`. When `Foo[Bar]` happens, it ends up
|
||||
/// calling `index`, and therefore, `main` prints `Indexing!`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(associated_types)]
|
||||
///
|
||||
/// use std::ops::Index;
|
||||
///
|
||||
/// #[derive(Copy)]
|
||||
/// struct Foo;
|
||||
/// struct Bar;
|
||||
///
|
||||
/// impl Index<Foo> for Foo {
|
||||
/// impl Index<Bar> for Foo {
|
||||
/// type Output = Foo;
|
||||
///
|
||||
/// fn index<'a>(&'a self, _index: &Foo) -> &'a Foo {
|
||||
/// fn index<'a>(&'a self, _index: &Bar) -> &'a Foo {
|
||||
/// println!("Indexing!");
|
||||
/// self
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// Foo[Foo];
|
||||
/// Foo[Bar];
|
||||
/// }
|
||||
/// ```
|
||||
#[lang="index"]
|
||||
|
@ -867,28 +866,27 @@ pub trait Index<Index: ?Sized> {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// A trivial implementation of `IndexMut`. When `Foo[Foo]` happens, it ends up
|
||||
/// A trivial implementation of `IndexMut`. When `Foo[Bar]` happens, it ends up
|
||||
/// calling `index_mut`, and therefore, `main` prints `Indexing!`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(associated_types)]
|
||||
///
|
||||
/// use std::ops::IndexMut;
|
||||
///
|
||||
/// #[derive(Copy)]
|
||||
/// struct Foo;
|
||||
/// struct Bar;
|
||||
///
|
||||
/// impl IndexMut<Foo> for Foo {
|
||||
/// impl IndexMut<Bar> for Foo {
|
||||
/// type Output = Foo;
|
||||
///
|
||||
/// fn index_mut<'a>(&'a mut self, _index: &Foo) -> &'a mut Foo {
|
||||
/// fn index_mut<'a>(&'a mut self, _index: &Bar) -> &'a mut Foo {
|
||||
/// println!("Indexing!");
|
||||
/// self
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// &mut Foo[Foo];
|
||||
/// &mut Foo[Bar];
|
||||
/// }
|
||||
/// ```
|
||||
#[lang="index_mut"]
|
||||
|
|
|
@ -21,11 +21,7 @@
|
|||
//! # Example
|
||||
//!
|
||||
//! ```ignore
|
||||
//! # fn main() {
|
||||
//! #![feature(globs)]
|
||||
//!
|
||||
//! use core::prelude::*;
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
// Reexported core operators
|
||||
|
|
|
@ -217,11 +217,9 @@
|
|||
//! makes it clear:
|
||||
//!
|
||||
//! ```
|
||||
//! # #![feature(macro_rules)]
|
||||
//! macro_rules! try {
|
||||
//! ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
|
||||
//! }
|
||||
//! # fn main() { }
|
||||
//! ```
|
||||
//!
|
||||
//! `try!` is imported by the prelude, and is available everywhere.
|
||||
|
|
|
@ -4168,6 +4168,27 @@ pub mod funcs {
|
|||
pub fn malloc(size: size_t) -> *mut c_void;
|
||||
pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
|
||||
pub fn free(p: *mut c_void);
|
||||
|
||||
/// Exits the running program in a possibly dangerous manner.
|
||||
///
|
||||
/// # Unsafety
|
||||
///
|
||||
/// While this forces your program to exit, it does so in a way that has
|
||||
/// consequences. This will skip all unwinding code, which means that anything
|
||||
/// relying on unwinding for cleanup (such as flushing and closing a buffer to a
|
||||
/// file) may act in an unexpected way.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// extern crate libc;
|
||||
///
|
||||
/// fn main() {
|
||||
/// unsafe {
|
||||
/// libc::exit(1);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn exit(status: c_int) -> !;
|
||||
pub fn _exit(status: c_int) -> !;
|
||||
pub fn atexit(cb: extern fn()) -> c_int;
|
||||
|
|
|
@ -44,6 +44,7 @@ extern crate rbml;
|
|||
extern crate collections;
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
||||
|
||||
extern crate "serialize" as rustc_serialize; // used by deriving
|
||||
|
||||
|
|
|
@ -8,10 +8,16 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![crate_name = "rustc_bitflags"]
|
||||
#![unstable]
|
||||
#![staged_api]
|
||||
#![crate_type = "rlib"]
|
||||
#![no_std]
|
||||
|
||||
//! A typesafe bitmask flag generator.
|
||||
|
||||
#[cfg(test)] #[macro_use] extern crate std;
|
||||
|
||||
/// The `bitflags!` macro generates a `struct` that holds a set of C-style
|
||||
/// bitmask flags. It is useful for creating typesafe wrappers for C APIs.
|
||||
///
|
||||
|
@ -21,6 +27,8 @@
|
|||
/// # Example
|
||||
///
|
||||
/// ```{.rust}
|
||||
/// #[macro_use] extern crate rustc_bitflags;
|
||||
///
|
||||
/// bitflags! {
|
||||
/// flags Flags: u32 {
|
||||
/// const FLAG_A = 0b00000001,
|
||||
|
@ -45,6 +53,8 @@
|
|||
/// The generated `struct`s can also be extended with type and trait implementations:
|
||||
///
|
||||
/// ```{.rust}
|
||||
/// #[macro_use] extern crate rustc_bitflags;
|
||||
///
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// bitflags! {
|
||||
|
@ -273,8 +283,8 @@ macro_rules! bitflags {
|
|||
#[cfg(test)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod tests {
|
||||
use hash::{self, SipHasher};
|
||||
use option::Option::{Some, None};
|
||||
use std::hash::{self, SipHasher};
|
||||
use std::option::Option::{Some, None};
|
||||
|
||||
bitflags! {
|
||||
#[doc = "> The first principle is that you must not fool yourself — and"]
|
|
@ -28,6 +28,7 @@
|
|||
#![allow(unknown_features)] #![feature(int_uint)]
|
||||
|
||||
extern crate libc;
|
||||
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
||||
|
||||
pub use self::OtherAttribute::*;
|
||||
pub use self::SpecialAttribute::*;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
||||
|
||||
extern crate rustc;
|
||||
|
||||
|
|
|
@ -26,15 +26,13 @@
|
|||
//!
|
||||
//! Some examples of the `format!` extension are:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn main() {
|
||||
//! ```
|
||||
//! format!("Hello"); // => "Hello"
|
||||
//! format!("Hello, {}!", "world"); // => "Hello, world!"
|
||||
//! format!("The number is {}", 1i); // => "The number is 1"
|
||||
//! format!("{:?}", (3i, 4i)); // => "(3i, 4i)"
|
||||
//! format!("{value}", value=4i); // => "4"
|
||||
//! format!("{} {}", 1i, 2u); // => "1 2"
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! From these, you can see that the first argument is a format string. It is
|
||||
|
@ -83,12 +81,10 @@
|
|||
//!
|
||||
//! For example, the following `format!` expressions all use named argument:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn main() {
|
||||
//! ```
|
||||
//! format!("{argument}", argument = "test"); // => "test"
|
||||
//! format!("{name} {}", 1i, name = 2i); // => "2 1"
|
||||
//! format!("{a} {c} {b}", a="a", b='b', c=3i); // => "a 3 b"
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! It is illegal to put positional parameters (those without names) after
|
||||
|
@ -288,8 +284,6 @@
|
|||
//! use std::fmt;
|
||||
//! use std::io;
|
||||
//!
|
||||
//! # #[allow(unused_must_use)]
|
||||
//! # fn main() {
|
||||
//! fmt::format(format_args!("this returns {}", "String"));
|
||||
//!
|
||||
//! let some_writer: &mut io::Writer = &mut io::stdout();
|
||||
|
@ -299,7 +293,6 @@
|
|||
//! write!(&mut io::stdout(), "{}", args);
|
||||
//! }
|
||||
//! my_fmt_fn(format_args!("or a {} too", "function"));
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! The result of the `format_args!` macro is a value of type `fmt::Arguments`.
|
||||
|
|
|
@ -934,16 +934,15 @@ unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -
|
|||
/// A `RefReader` is a struct implementing `Reader` which contains a reference
|
||||
/// to another reader. This is often useful when composing streams.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() {}
|
||||
/// # fn process_input<R: Reader>(r: R) {}
|
||||
/// # fn foo() {
|
||||
/// use std::io;
|
||||
/// use std::io::ByRefReader;
|
||||
/// use std::io::util::LimitReader;
|
||||
///
|
||||
/// fn process_input<R: Reader>(r: R) {}
|
||||
///
|
||||
/// let mut stream = io::stdin();
|
||||
///
|
||||
/// // Only allow the function to process at most one kilobyte of input
|
||||
|
@ -953,8 +952,6 @@ unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -
|
|||
/// }
|
||||
///
|
||||
/// // 'stream' is still available for use here
|
||||
///
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct RefReader<'a, R:'a> {
|
||||
/// The underlying reader which this is referencing
|
||||
|
@ -1269,12 +1266,11 @@ impl<'a> Writer for &'a mut (Writer+'a) {
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() {}
|
||||
/// # fn process_input<R: Reader>(r: R) {}
|
||||
/// # fn foo () {
|
||||
/// use std::io::util::TeeReader;
|
||||
/// use std::io::{stdin, ByRefWriter};
|
||||
///
|
||||
/// fn process_input<R: Reader>(r: R) {}
|
||||
///
|
||||
/// let mut output = Vec::new();
|
||||
///
|
||||
/// {
|
||||
|
@ -1285,7 +1281,6 @@ impl<'a> Writer for &'a mut (Writer+'a) {
|
|||
/// }
|
||||
///
|
||||
/// println!("input processed: {:?}", output);
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct RefWriter<'a, W:'a> {
|
||||
/// The underlying writer which this is referencing
|
||||
|
@ -1705,19 +1700,19 @@ pub enum FileType {
|
|||
/// A structure used to describe metadata information about a file. This
|
||||
/// structure is created through the `stat` method on a `Path`.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #![allow(unstable)]
|
||||
///
|
||||
/// use std::io::fs::PathExtensions;
|
||||
///
|
||||
/// ```
|
||||
/// # use std::io::fs::PathExtensions;
|
||||
/// # fn main() {}
|
||||
/// # fn foo() {
|
||||
/// let info = match Path::new("foo.txt").stat() {
|
||||
/// Ok(stat) => stat,
|
||||
/// Err(e) => panic!("couldn't read foo.txt: {}", e),
|
||||
/// };
|
||||
///
|
||||
/// println!("byte size: {}", info.size);
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Copy, Hash)]
|
||||
pub struct FileStat {
|
||||
|
|
|
@ -168,9 +168,7 @@ impl UnixListener {
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() {}
|
||||
/// # fn foo() {
|
||||
/// # #![allow(unused_must_use)]
|
||||
/// use std::io::net::pipe::UnixListener;
|
||||
/// use std::io::{Listener, Acceptor};
|
||||
///
|
||||
|
|
|
@ -272,12 +272,10 @@ impl sys_common::AsInner<TcpStreamImp> for TcpStream {
|
|||
/// A structure representing a socket server. This listener is used to create a
|
||||
/// `TcpAcceptor` which can be used to accept sockets on a local port.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
/// # fn foo() {
|
||||
/// # #![allow(dead_code)]
|
||||
/// use std::io::{TcpListener, TcpStream};
|
||||
/// use std::io::{Acceptor, Listener};
|
||||
/// use std::thread::Thread;
|
||||
|
|
|
@ -27,10 +27,9 @@ use sys::timer::Timer as TimerImp;
|
|||
/// period of time. Handles to this timer can also be created in the form of
|
||||
/// receivers which will receive notifications over time.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() {}
|
||||
/// # fn foo() {
|
||||
/// use std::io::Timer;
|
||||
/// use std::time::Duration;
|
||||
|
@ -54,7 +53,6 @@ use sys::timer::Timer as TimerImp;
|
|||
/// the `io::timer` module.
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() {}
|
||||
/// # fn foo() {
|
||||
/// use std::io::timer;
|
||||
/// use std::time::Duration;
|
||||
|
|
|
@ -111,7 +111,7 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(old_impl_check)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![allow(unknown_features)] #![feature(int_uint)]
|
||||
#![feature(int_uint)]
|
||||
|
||||
// Don't link to std. We are std.
|
||||
#![no_std]
|
||||
|
@ -136,6 +136,8 @@ extern crate alloc;
|
|||
extern crate unicode;
|
||||
extern crate libc;
|
||||
|
||||
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
||||
|
||||
// Make std testable by not duplicating lang items. See #2912
|
||||
#[cfg(test)] extern crate "std" as realstd;
|
||||
#[cfg(test)] pub use realstd::marker;
|
||||
|
@ -181,9 +183,6 @@ pub use unicode::char;
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[macro_use]
|
||||
pub mod bitflags;
|
||||
|
||||
mod rtdeps;
|
||||
|
||||
/* The Prelude. */
|
||||
|
|
|
@ -122,16 +122,18 @@ macro_rules! try {
|
|||
/// receivers. It places no restrictions on the types of receivers given to
|
||||
/// this macro, this can be viewed as a heterogeneous select.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::thread::Thread;
|
||||
/// use std::sync::mpsc::channel;
|
||||
/// use std::sync::mpsc;
|
||||
///
|
||||
/// let (tx1, rx1) = channel();
|
||||
/// let (tx2, rx2) = channel();
|
||||
/// # fn long_running_task() {}
|
||||
/// # fn calculate_the_answer() -> int { 42i }
|
||||
/// // two placeholder functions for now
|
||||
/// fn long_running_task() {}
|
||||
/// fn calculate_the_answer() -> u32 { 42 }
|
||||
///
|
||||
/// let (tx1, rx1) = mpsc::channel();
|
||||
/// let (tx2, rx2) = mpsc::channel();
|
||||
///
|
||||
/// Thread::spawn(move|| { long_running_task(); tx1.send(()).unwrap(); });
|
||||
/// Thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); });
|
||||
|
@ -251,13 +253,13 @@ pub mod builtin {
|
|||
/// statement or expression position, meaning this macro may be difficult to
|
||||
/// use in some situations.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(concat_idents)]
|
||||
///
|
||||
/// # fn main() {
|
||||
/// fn foobar() -> int { 23 }
|
||||
/// fn foobar() -> u32 { 23 }
|
||||
///
|
||||
/// let f = concat_idents!(foo, bar);
|
||||
/// println!("{}", f());
|
||||
|
|
|
@ -11,14 +11,18 @@
|
|||
//! A type representing values that may be computed concurrently and operations
|
||||
//! for working with them.
|
||||
//!
|
||||
//! # Example
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```
|
||||
//! use std::sync::Future;
|
||||
//! # fn fib(n: uint) -> uint {42};
|
||||
//! # fn make_a_sandwich() {};
|
||||
//! let mut delayed_fib = Future::spawn(move|| { fib(5000) });
|
||||
//! make_a_sandwich();
|
||||
//!
|
||||
//! // a fake, for now
|
||||
//! fn fib(n: u32) -> u32 { 42 };
|
||||
//!
|
||||
//! let mut delayed_fib = Future::spawn(move || fib(5000));
|
||||
//!
|
||||
//! // do stuff...
|
||||
//!
|
||||
//! println!("fib(5000) = {}", delayed_fib.get())
|
||||
//! ```
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ extern crate serialize;
|
|||
extern crate term;
|
||||
extern crate libc;
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
||||
|
||||
extern crate "serialize" as rustc_serialize; // used by deriving
|
||||
|
||||
|
|
|
@ -14,5 +14,5 @@
|
|||
extern crate libc;
|
||||
|
||||
fn main() {
|
||||
println!("{}", 1.0 as *libc::FILE); // Can't cast float to foreign.
|
||||
println!("{:?}", 1.0 as *const libc::FILE); // Can't cast float to foreign.
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue