mirror of https://github.com/rust-lang/rust.git
auto merge of #11405 : huonw/rust/moredocs, r=huonw
Various documentation changes, change the 'borrowed pointer' terminology to 'reference', fix a problem with 'make dist' on windows.
This commit is contained in:
commit
464d1d044e
|
@ -410,6 +410,7 @@ export CFG_SRC_DIR
|
|||
export CFG_BUILD_DIR
|
||||
export CFG_VERSION
|
||||
export CFG_VERSION_WIN
|
||||
export CFG_RELEASE
|
||||
export CFG_BUILD
|
||||
export CFG_LLVM_ROOT
|
||||
export CFG_ENABLE_MINGW_CROSS
|
||||
|
|
|
@ -806,6 +806,7 @@ do
|
|||
make_dir $h/test/doc-guide-container
|
||||
make_dir $h/test/doc-guide-tasks
|
||||
make_dir $h/test/doc-guide-conditions
|
||||
make_dir $h/test/doc-complement-cheatsheet
|
||||
make_dir $h/test/doc-rust
|
||||
done
|
||||
|
||||
|
|
|
@ -6,41 +6,41 @@
|
|||
|
||||
Use [`ToStr`](http://static.rust-lang.org/doc/master/std/to_str/trait.ToStr.html).
|
||||
|
||||
```rust
|
||||
~~~
|
||||
let x: int = 42;
|
||||
let y: ~str = x.to_str();
|
||||
```
|
||||
~~~
|
||||
|
||||
**String to int**
|
||||
|
||||
Use [`FromStr`](http://static.rust-lang.org/doc/master/std/from_str/trait.FromStr.html), and its helper function, [`from_str`](http://static.rust-lang.org/doc/master/std/from_str/fn.from_str.html).
|
||||
|
||||
```rust
|
||||
~~~
|
||||
let x: Option<int> = from_str("42");
|
||||
let y: int = x.unwrap();
|
||||
```
|
||||
~~~
|
||||
|
||||
**Int to string, in non-base-10**
|
||||
|
||||
Use [`ToStrRadix`](http://static.rust-lang.org/doc/master/std/num/trait.ToStrRadix.html).
|
||||
|
||||
```rust
|
||||
~~~
|
||||
use std::num::ToStrRadix;
|
||||
|
||||
let x: int = 42;
|
||||
let y: ~str = x.to_str_radix(16);
|
||||
```
|
||||
~~~
|
||||
|
||||
**String to int, in non-base-10**
|
||||
|
||||
Use [`FromStrRadix`](http://static.rust-lang.org/doc/master/std/num/trait.FromStrRadix.html), and its helper function, [`from_str_radix`](http://static.rust-lang.org/doc/master/std/num/fn.from_str_radix.html).
|
||||
|
||||
```rust
|
||||
~~~
|
||||
use std::num::from_str_radix;
|
||||
|
||||
let x: Option<int> = from_str_radix("deadbeef", 16);
|
||||
let y: int = x.unwrap();
|
||||
```
|
||||
let x: Option<i64> = from_str_radix("deadbeef", 16);
|
||||
let y: i64 = x.unwrap();
|
||||
~~~
|
||||
|
||||
# File operations
|
||||
|
||||
|
@ -48,27 +48,30 @@ let y: int = x.unwrap();
|
|||
|
||||
Use [`File::open`](http://static.rust-lang.org/doc/master/std/io/fs/struct.File.html#method.open) to create a [`File`](http://static.rust-lang.org/doc/master/std/io/fs/struct.File.html) struct, which implements the [`Reader`](http://static.rust-lang.org/doc/master/std/io/trait.Reader.html) trait.
|
||||
|
||||
```rust
|
||||
~~~ {.xfail-test}
|
||||
use std::path::Path;
|
||||
use std::io::fs::File;
|
||||
|
||||
let path : Path = Path::new("Doc-FAQ-Cheatsheet.md");
|
||||
let on_error = || fail!("open of {:?} failed", path);
|
||||
let reader : File = File::open(&path).unwrap_or_else(on_error);
|
||||
```
|
||||
~~~
|
||||
|
||||
## How do I iterate over the lines in a file?
|
||||
|
||||
Use the [`lines`](http://static.rust-lang.org/doc/master/std/io/trait.Buffer.html#method.lines) method on a [`BufferedReader`](http://static.rust-lang.org/doc/master/std/io/buffered/struct.BufferedReader.html).
|
||||
|
||||
```rust
|
||||
~~~
|
||||
use std::io::buffered::BufferedReader;
|
||||
# use std::io::mem::MemReader;
|
||||
|
||||
# let reader = MemReader::new(~[]);
|
||||
|
||||
let mut reader = BufferedReader::new(reader);
|
||||
for line in reader.lines() {
|
||||
print!("line: {}", line);
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
# String operations
|
||||
|
||||
|
@ -76,10 +79,10 @@ for line in reader.lines() {
|
|||
|
||||
Use the [`find_str`](http://static.rust-lang.org/doc/master/std/str/trait.StrSlice.html#tymethod.find_str) method.
|
||||
|
||||
```rust
|
||||
~~~
|
||||
let str = "Hello, this is some random string";
|
||||
let index: Option<uint> = str.find_str("rand");
|
||||
```
|
||||
~~~
|
||||
|
||||
# Containers
|
||||
|
||||
|
@ -87,24 +90,24 @@ let index: Option<uint> = str.find_str("rand");
|
|||
|
||||
The [`Container`](http://static.rust-lang.org/doc/master/std/container/trait.Container.html) trait provides the `len` method.
|
||||
|
||||
```rust
|
||||
~~~
|
||||
let u: ~[u32] = ~[0, 1, 2];
|
||||
let v: &[u32] = &[0, 1, 2, 3];
|
||||
let w: [u32, .. 5] = [0, 1, 2, 3, 4];
|
||||
|
||||
println!("u: {}, v: {}, w: {}", u.len(), v.len(), w.len()); // 3, 4, 5
|
||||
```
|
||||
~~~
|
||||
|
||||
## How do I iterate over a vector?
|
||||
|
||||
Use the [`iter`](http://static.rust-lang.org/doc/master/std/vec/trait.ImmutableVector.html#tymethod.iter) method.
|
||||
|
||||
```rust
|
||||
~~~
|
||||
let values: ~[int] = ~[1, 2, 3, 4, 5];
|
||||
for value in values.iter() { // value: &int
|
||||
println!("{}", *value);
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
(See also [`mut_iter`](http://static.rust-lang.org/doc/master/std/vec/trait.MutableVector.html#tymethod.mut_iter) which yields `&mut int` and [`move_iter`](http://static.rust-lang.org/doc/master/std/vec/trait.OwnedVector.html#tymethod.move_iter) which yields `int` while consuming the `values` vector.)
|
||||
|
||||
|
@ -112,7 +115,7 @@ for value in values.iter() { // value: &int
|
|||
|
||||
## How do I store a function in a struct?
|
||||
|
||||
```rust
|
||||
~~~
|
||||
struct Foo {
|
||||
myfunc: fn(int, uint) -> i32
|
||||
}
|
||||
|
@ -131,7 +134,7 @@ fn main() {
|
|||
println!("{}", (f.myfunc)(1, 2));
|
||||
println!("{}", (g.myfunc)(3, 4));
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
Note that the parenthesis surrounding `f.myfunc` are necessary: they are how Rust disambiguates field lookup and method call. The `'a` on `FooClosure` is the lifetime of the closure's environment pointer.
|
||||
|
||||
|
@ -139,16 +142,19 @@ Note that the parenthesis surrounding `f.myfunc` are necessary: they are how Rus
|
|||
|
||||
[Phantom types](http://www.haskell.org/haskellwiki/Phantom_type) are those that cannot be constructed at compile time. To express these in Rust, zero-variant `enum`s can be used:
|
||||
|
||||
```rust
|
||||
~~~
|
||||
enum Open {}
|
||||
enum Closed {}
|
||||
```
|
||||
~~~
|
||||
|
||||
Phantom types are useful for enforcing state at compile time. For example:
|
||||
|
||||
```rust
|
||||
~~~
|
||||
struct Door<State>(~str);
|
||||
|
||||
struct Open;
|
||||
struct Closed;
|
||||
|
||||
fn close(Door(name): Door<Open>) -> Door<Closed> {
|
||||
Door::<Closed>(name)
|
||||
}
|
||||
|
@ -157,20 +163,25 @@ fn open(Door(name): Door<Closed>) -> Door<Open> {
|
|||
Door::<Open>(name)
|
||||
}
|
||||
|
||||
let _ = close(Door::<Open>(~"front")); // ok
|
||||
let _ = close(Door::<Open>(~"front"));
|
||||
~~~
|
||||
|
||||
Attempting to close a closed door is prevented statically:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
let _ = close(Door::<Closed>(~"front")); // error: mismatched types: expected `main::Door<main::Open>` but found `main::Door<main::Closed>`
|
||||
```
|
||||
~~~
|
||||
|
||||
# FFI (Foreign Function Interface)
|
||||
|
||||
## C function signature conversions
|
||||
|
||||
Description | C signature | Equivalent Rust signature
|
||||
----------------------|----------------------------------------------|------------------------------------------
|
||||
no parameters | `void foo(void);` | `fn foo();`
|
||||
return value | `int foo(void);` | `fn foo() -> c_int;`
|
||||
function parameters | `void foo(int x, int y);` | `fn foo(x: int, y: int);`
|
||||
in-out pointers | `void foo(const int* in_ptr, int* out_ptr);` | `fn foo(in_ptr: *c_int, out_ptr: *mut c_int);`
|
||||
Description C signature Equivalent Rust signature
|
||||
---------------------- ---------------------------------------------- ------------------------------------------
|
||||
no parameters `void foo(void);` `fn foo();`
|
||||
return value `int foo(void);` `fn foo() -> c_int;`
|
||||
function parameters `void foo(int x, int y);` `fn foo(x: int, y: int);`
|
||||
in-out pointers `void foo(const int* in_ptr, int* out_ptr);` `fn foo(in_ptr: *c_int, out_ptr: *mut c_int);`
|
||||
|
||||
Note: The Rust signatures should be wrapped in an `extern "ABI" { ... }` block.
|
||||
|
||||
|
@ -178,19 +189,19 @@ Note: The Rust signatures should be wrapped in an `extern "ABI" { ... }` block.
|
|||
|
||||
You might see things like this in C APIs:
|
||||
|
||||
```c
|
||||
~~~ {.notrust}
|
||||
typedef struct Window Window;
|
||||
Window* createWindow(int width, int height);
|
||||
```
|
||||
~~~
|
||||
|
||||
You can use a zero-element `enum` ([phantom type](#how-do-i-express-phantom-types)) to represent the opaque object handle. The FFI would look like this:
|
||||
|
||||
```rust
|
||||
~~~ {.xfail-test}
|
||||
enum Window {}
|
||||
extern "C" {
|
||||
fn createWindow(width: c_int, height: c_int) -> *Window;
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
Using a phantom type ensures that the handles cannot be (safely) constructed in client code.
|
||||
|
||||
|
|
|
@ -218,13 +218,13 @@ They start small (ideally in the hundreds of bytes) and expand dynamically by ca
|
|||
* Managed boxes may not be shared between tasks
|
||||
* Owned boxes may be transferred (moved) between tasks
|
||||
|
||||
## What is the difference between a borrowed pointer (`&`) and managed and owned boxes?
|
||||
## What is the difference between a reference (`&`) and managed and owned boxes?
|
||||
|
||||
* Borrowed pointers point to the interior of a stack _or_ heap allocation
|
||||
* Borrowed pointers can only be formed when it will provably be outlived by the referent
|
||||
* Borrowed pointers to managed box pointers keep the managed boxes alive
|
||||
* Borrowed pointers to owned boxes prevent their ownership from being transferred
|
||||
* Borrowed pointers employ region-based alias analysis to ensure correctness
|
||||
* References point to the interior of a stack _or_ heap allocation
|
||||
* References can only be formed when it will provably be outlived by the referent
|
||||
* References to managed box pointers keep the managed boxes alive
|
||||
* References to owned boxes prevent their ownership from being transferred
|
||||
* References employ region-based alias analysis to ensure correctness
|
||||
|
||||
## Why aren't function signatures inferred? Why only local slots?
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% Rust Condition and Error-handling Guide
|
||||
% The Rust Condition and Error-handling Guide
|
||||
|
||||
# Introduction
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% Containers and Iterators Guide
|
||||
% The Rust Containers and Iterators Guide
|
||||
|
||||
# Containers
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% Rust Foreign Function Interface Guide
|
||||
% The Rust Foreign Function Interface Guide
|
||||
|
||||
# Introduction
|
||||
|
||||
|
@ -417,7 +417,7 @@ However, there are currently no guarantees about the layout of an `enum`.
|
|||
|
||||
Rust's owned and managed boxes use non-nullable pointers as handles which point to the contained
|
||||
object. However, they should not be manually created because they are managed by internal
|
||||
allocators. Borrowed pointers can safely be assumed to be non-nullable pointers directly to the
|
||||
allocators. References can safely be assumed to be non-nullable pointers directly to the
|
||||
type. However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so
|
||||
prefer using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions
|
||||
about them.
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
% Rust Borrowed Pointers Guide
|
||||
% The Rust References and Lifetimes Guide
|
||||
|
||||
# Introduction
|
||||
|
||||
Borrowed pointers are one of the more flexible and powerful tools available in
|
||||
Rust. A borrowed pointer can point anywhere: into the managed or exchange
|
||||
References are one of the more flexible and powerful tools available in
|
||||
Rust. A reference can point anywhere: into the managed or exchange
|
||||
heap, into the stack, and even into the interior of another data structure. A
|
||||
borrowed pointer is as flexible as a C pointer or C++ reference. However,
|
||||
reference is as flexible as a C pointer or C++ reference. However,
|
||||
unlike C and C++ compilers, the Rust compiler includes special static checks
|
||||
that ensure that programs use borrowed pointers safely. Another advantage of
|
||||
borrowed pointers is that they are invisible to the garbage collector, so
|
||||
working with borrowed pointers helps reduce the overhead of automatic memory
|
||||
that ensure that programs use references safely. Another advantage of
|
||||
references is that they are invisible to the garbage collector, so
|
||||
working with references helps reduce the overhead of automatic memory
|
||||
management.
|
||||
|
||||
Despite their complete safety, a borrowed pointer's representation at runtime
|
||||
Despite their complete safety, a reference's representation at runtime
|
||||
is the same as that of an ordinary pointer in a C program. They introduce zero
|
||||
overhead. The compiler does all safety checks at compile time.
|
||||
|
||||
Although borrowed pointers have rather elaborate theoretical
|
||||
Although references have rather elaborate theoretical
|
||||
underpinnings (region pointers), the core concepts will be familiar to
|
||||
anyone who has worked with C or C++. Therefore, the best way to explain
|
||||
how they are used—and their limitations—is probably just to work
|
||||
|
@ -24,8 +24,8 @@ through several examples.
|
|||
|
||||
# By example
|
||||
|
||||
Borrowed pointers are called *borrowed* because they are only valid for
|
||||
a limited duration. Borrowed pointers never claim any kind of ownership
|
||||
References, sometimes known as *borrowed pointers*, are only valid for
|
||||
a limited duration. References never claim any kind of ownership
|
||||
over the data that they point to: instead, they are used for cases
|
||||
where you would like to use data for a short time.
|
||||
|
||||
|
@ -55,7 +55,7 @@ define it this way, calling the function will cause the points to be
|
|||
copied. For points, this is probably not so bad, but often copies are
|
||||
expensive. Worse, if the data type contains mutable fields, copying can change
|
||||
the semantics of your program in unexpected ways. So we'd like to define a
|
||||
function that takes the points by pointer. We can use borrowed pointers to do
|
||||
function that takes the points by pointer. We can use references to do
|
||||
this:
|
||||
|
||||
~~~
|
||||
|
@ -89,7 +89,7 @@ name for the same data.
|
|||
|
||||
In contrast, we can pass the boxes `managed_box` and `owned_box` to
|
||||
`compute_distance` directly. The compiler automatically converts a box like
|
||||
`@Point` or `~Point` to a borrowed pointer like `&Point`. This is another form
|
||||
`@Point` or `~Point` to a reference like `&Point`. This is another form
|
||||
of borrowing: in this case, the caller lends the contents of the managed or
|
||||
owned box to the callee.
|
||||
|
||||
|
@ -100,7 +100,7 @@ addition, the compiler will reject any code that might cause the borrowed
|
|||
value to be freed or overwrite its component fields with values of different
|
||||
types (I'll get into what kinds of actions those are shortly). This rule
|
||||
should make intuitive sense: you must wait for a borrower to return the value
|
||||
that you lent it (that is, wait for the borrowed pointer to go out of scope)
|
||||
that you lent it (that is, wait for the reference to go out of scope)
|
||||
before you can make full use of it again.
|
||||
|
||||
# Other uses for the & operator
|
||||
|
@ -114,7 +114,7 @@ let on_the_stack: Point = Point {x: 3.0, y: 4.0};
|
|||
|
||||
This declaration means that code can only pass `Point` by value to other
|
||||
functions. As a consequence, we had to explicitly take the address of
|
||||
`on_the_stack` to get a borrowed pointer. Sometimes however it is more
|
||||
`on_the_stack` to get a reference. Sometimes however it is more
|
||||
convenient to move the & operator into the definition of `on_the_stack`:
|
||||
|
||||
~~~
|
||||
|
@ -180,7 +180,7 @@ as well as from the managed box, and then compute the distance between them.
|
|||
|
||||
We’ve seen a few examples so far of borrowing heap boxes, both managed
|
||||
and owned. Up till this point, we’ve glossed over issues of
|
||||
safety. As stated in the introduction, at runtime a borrowed pointer
|
||||
safety. As stated in the introduction, at runtime a reference
|
||||
is simply a pointer, nothing more. Therefore, avoiding C's problems
|
||||
with dangling pointers requires a compile-time safety check.
|
||||
|
||||
|
@ -195,7 +195,7 @@ broader scope than the pointer itself), the compiler reports an
|
|||
error. We'll be discussing lifetimes more in the examples to come, and
|
||||
a more thorough introduction is also available.
|
||||
|
||||
When the `&` operator creates a borrowed pointer, the compiler must
|
||||
When the `&` operator creates a reference, the compiler must
|
||||
ensure that the pointer remains valid for its entire
|
||||
lifetime. Sometimes this is relatively easy, such as when taking the
|
||||
address of a local variable or a field that is stored on the stack:
|
||||
|
@ -209,7 +209,7 @@ fn example1() {
|
|||
} // -+
|
||||
~~~
|
||||
|
||||
Here, the lifetime of the borrowed pointer `y` is simply L, the
|
||||
Here, the lifetime of the reference `y` is simply L, the
|
||||
remainder of the function body. The compiler need not do any other
|
||||
work to prove that code will not free `x.f`. This is true even if the
|
||||
code mutates `x`.
|
||||
|
@ -384,7 +384,7 @@ enum Shape {
|
|||
~~~
|
||||
|
||||
Now we might write a function to compute the area of a shape. This
|
||||
function takes a borrowed pointer to a shape, to avoid the need for
|
||||
function takes a reference to a shape, to avoid the need for
|
||||
copying.
|
||||
|
||||
~~~
|
||||
|
@ -466,19 +466,19 @@ same rules as the ones we saw for borrowing the interior of a owned
|
|||
box: it must be able to guarantee that the `enum` will not be
|
||||
overwritten for the duration of the borrow. In fact, the compiler
|
||||
would accept the example we gave earlier. The example is safe because
|
||||
the shape pointer has type `&Shape`, which means "borrowed pointer to
|
||||
the shape pointer has type `&Shape`, which means "reference to
|
||||
immutable memory containing a `shape`". If, however, the type of that
|
||||
pointer were `&mut Shape`, then the ref binding would be ill-typed.
|
||||
Just as with owned boxes, the compiler will permit `ref` bindings
|
||||
into data owned by the stack frame even if the data are mutable,
|
||||
but otherwise it requires that the data reside in immutable memory.
|
||||
|
||||
# Returning borrowed pointers
|
||||
# Returning references
|
||||
|
||||
So far, all of the examples we have looked at, use borrowed pointers in a
|
||||
So far, all of the examples we have looked at, use references in a
|
||||
“downward” direction. That is, a method or code block creates a
|
||||
borrowed pointer, then uses it within the same scope. It is also
|
||||
possible to return borrowed pointers as the result of a function, but
|
||||
reference, then uses it within the same scope. It is also
|
||||
possible to return references as the result of a function, but
|
||||
as we'll see, doing so requires some explicit annotation.
|
||||
|
||||
For example, we could write a subroutine like this:
|
||||
|
@ -496,7 +496,7 @@ explicitly. So in effect, this function declares that it takes a
|
|||
pointer with lifetime `r` and returns a pointer with that same
|
||||
lifetime.
|
||||
|
||||
In general, it is only possible to return borrowed pointers if they
|
||||
In general, it is only possible to return references if they
|
||||
are derived from a parameter to the procedure. In that case, the
|
||||
pointer result will always have the same lifetime as one of the
|
||||
parameters; named lifetimes indicate which parameter that
|
||||
|
@ -532,10 +532,10 @@ fn get_x_sh(p: @Point) -> &f64 {
|
|||
~~~
|
||||
|
||||
Here, the function `get_x_sh()` takes a managed box as input and
|
||||
returns a borrowed pointer. As before, the lifetime of the borrowed
|
||||
pointer that will be returned is a parameter (specified by the
|
||||
caller). That means that `get_x_sh()` promises to return a borrowed
|
||||
pointer that is valid for as long as the caller would like: this is
|
||||
returns a reference. As before, the lifetime of the reference
|
||||
that will be returned is a parameter (specified by the
|
||||
caller). That means that `get_x_sh()` promises to return a reference
|
||||
that is valid for as long as the caller would like: this is
|
||||
subtly different from the first example, which promised to return a
|
||||
pointer that was valid for as long as its pointer argument was valid.
|
||||
|
||||
|
@ -551,10 +551,10 @@ valid at all once it returns, as the parameter `p` may or may not be
|
|||
live in the caller. Therefore, the compiler will report an error here.
|
||||
|
||||
In general, if you borrow a managed (or owned) box to create a
|
||||
borrowed pointer, the pointer will only be valid within the function
|
||||
and cannot be returned. This is why the typical way to return borrowed
|
||||
pointers is to take borrowed pointers as input (the only other case in
|
||||
which it can be legal to return a borrowed pointer is if the pointer
|
||||
reference, it will only be valid within the function
|
||||
and cannot be returned. This is why the typical way to return references
|
||||
is to take references as input (the only other case in
|
||||
which it can be legal to return a reference is if it
|
||||
points at a static constant).
|
||||
|
||||
# Named lifetimes
|
||||
|
@ -577,7 +577,7 @@ fn select<'r, T>(shape: &'r Shape, threshold: f64,
|
|||
}
|
||||
~~~
|
||||
|
||||
This function takes three borrowed pointers and assigns each the same
|
||||
This function takes three references and assigns each the same
|
||||
lifetime `r`. In practice, this means that, in the caller, the
|
||||
lifetime `r` will be the *intersection of the lifetime of the three
|
||||
region parameters*. This may be overly conservative, as in this
|
||||
|
@ -657,7 +657,7 @@ This is equivalent to the previous definition.
|
|||
|
||||
# Conclusion
|
||||
|
||||
So there you have it: a (relatively) brief tour of the borrowed pointer
|
||||
So there you have it: a (relatively) brief tour of the lifetime
|
||||
system. For more details, we refer to the (yet to be written) reference
|
||||
document on borrowed pointers, which will explain the full notation
|
||||
document on references, which will explain the full notation
|
||||
and give more examples.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% Rust Macros Guide
|
||||
% The Rust Macros Guide
|
||||
|
||||
# Introduction
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
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
|
||||
be confusing for people coming from other languages that support pointers, such
|
||||
as C++. This tutorial will help you understand this important topic.
|
||||
as C++. This guide will help you understand this important topic.
|
||||
|
||||
# You don't actually need pointers
|
||||
|
||||
|
@ -13,8 +13,7 @@ that emphasizes safety. Pointers, as the joke goes, are very pointy: it's easy
|
|||
to accidentally stab yourself. Therefore, Rust is made in a way such that you
|
||||
don't need them very often.
|
||||
|
||||
"But tutorial!" you may cry. "My co-worker wrote a function that looks like
|
||||
this:
|
||||
"But guide!" you may cry. "My co-worker wrote a function that looks like this:
|
||||
|
||||
~~~rust
|
||||
fn succ(x: &int) -> int { *x + 1 }
|
||||
|
@ -22,7 +21,7 @@ fn succ(x: &int) -> int { *x + 1 }
|
|||
|
||||
So I wrote this code to try it out:
|
||||
|
||||
~~~rust {.xfail-test}
|
||||
~~~rust{.xfail-test}
|
||||
fn main() {
|
||||
let number = 5;
|
||||
let succ_number = succ(number);
|
||||
|
@ -74,7 +73,7 @@ However.
|
|||
Here are the use-cases for pointers. I've prefixed them with the name of the
|
||||
pointer that satisfies that use-case:
|
||||
|
||||
1. Owned: ~Trait must be a pointer, becuase you don't know the size of the
|
||||
1. Owned: ~Trait must be a pointer, because you don't know the size of the
|
||||
object, so indirection is mandatory.
|
||||
2. Owned: You need a recursive data structure. These can be infinite sized, so
|
||||
indirection is mandatory.
|
||||
|
@ -86,18 +85,18 @@ common, such as C++, please read "A note..." below.
|
|||
or impossible. This is only often useful when a program is very large or very
|
||||
complicated. Using a managed pointer will activate Rust's garbage collection
|
||||
mechanism.
|
||||
5: Borrowed: You're writing a function, and you need a pointer, but you don't
|
||||
care about its ownership. If you make the argument a borrowed pointer, callers
|
||||
5. Reference: You're writing a function, and you need a pointer, but you don't
|
||||
care about its ownership. If you make the argument a reference, callers
|
||||
can send in whatever kind they want.
|
||||
|
||||
Five exceptions. That's it. Otherwise, you shouldn't need them. Be skeptical
|
||||
Five exceptions. That's it. Otherwise, you shouldn't need them. Be sceptical
|
||||
of pointers in Rust: use them for a deliberate purpose, not just to make the
|
||||
compiler happy.
|
||||
|
||||
## A note for those proficient in pointers
|
||||
|
||||
If you're coming to Rust from a language like C or C++, you may be used to
|
||||
passing things by reference, or passing things by pointer. In some langauges,
|
||||
passing things by reference, or passing things by pointer. In some languages,
|
||||
like Java, you can't even have objects without a pointer to them. Therefore, if
|
||||
you were writing this Rust code:
|
||||
|
||||
|
@ -151,7 +150,7 @@ fn main() {
|
|||
}
|
||||
~~~
|
||||
|
||||
But won't this be inefficent? Well, that's a complicated question, but it's
|
||||
But won't this be inefficient? Well, that's a complicated question, but it's
|
||||
important to know that Rust, like C and C++, store aggregate data types
|
||||
'unboxed,' whereas languages like Java and Ruby store these types as 'boxed.'
|
||||
For smaller structs, this way will be more efficient. For larger ones, it may
|
||||
|
@ -174,7 +173,7 @@ These two properties make for three use cases.
|
|||
|
||||
## References to Traits
|
||||
|
||||
Traits must be referenced through a pointer, becuase the struct that implements
|
||||
Traits must be referenced through a pointer, because the struct that implements
|
||||
the trait may be a different size than a different struct that implements the
|
||||
trait. Therefore, unboxed traits don't make any sense, and aren't allowed.
|
||||
|
||||
|
@ -200,7 +199,7 @@ This prints:
|
|||
Cons(1, ~Cons(2, ~Cons(3, ~Nil)))
|
||||
~~~
|
||||
|
||||
The inner lists _must_ be an owned pointer, becuase we can't know how many
|
||||
The inner lists _must_ be an owned pointer, because we can't know how many
|
||||
elements are in the list. Without knowing the length, we don't know the size,
|
||||
and therefore require the indirection that pointers offer.
|
||||
|
||||
|
@ -250,13 +249,19 @@ struct.
|
|||
|
||||
# Managed Pointers
|
||||
|
||||
> **Note**: the `@` form of managed pointers is deprecated and behind a
|
||||
> feature gate (it requires a `#[feature(managed_pointers)];` attribute on
|
||||
> the crate root; remember the semicolon!). There are replacements, currently
|
||||
> there is `std::rc::Rc` and `std::gc::Gc` for shared ownership via reference
|
||||
> counting and garbage collection respectively.
|
||||
|
||||
Managed pointers, notated by an `@`, are used when having a single owner for
|
||||
some data isn't convenient or possible. This generally happens when your
|
||||
program is very large and complicated.
|
||||
|
||||
For example, let's say you're using an owned pointer, and you want to do this:
|
||||
|
||||
~~~rust {.xfail-test}
|
||||
~~~rust{.xfail-test}
|
||||
struct Point {
|
||||
x: int,
|
||||
y: int,
|
||||
|
@ -310,14 +315,14 @@ managed pointers:
|
|||
1. They activate Rust's garbage collector. Other pointer types don't share this
|
||||
drawback.
|
||||
2. You cannot pass this data to another task. Shared ownership across
|
||||
concurrency boundaries is the source of endless pain in other langauges, so
|
||||
concurrency boundaries is the source of endless pain in other languages, so
|
||||
Rust does not let you do this.
|
||||
|
||||
# Borrowed Pointers
|
||||
# References
|
||||
|
||||
Borrowed pointers are the third major kind of pointer Rust supports. They are
|
||||
References are the third major kind of pointer Rust supports. They are
|
||||
simultaneously the simplest and the most complicated kind. Let me explain:
|
||||
they're called 'borrowed' pointers because they claim no ownership over the
|
||||
references are considered 'borrowed' because they claim no ownership over the
|
||||
data they're pointing to. They're just borrowing it for a while. So in that
|
||||
sense, they're simple: just keep whatever ownership the data already has. For
|
||||
example:
|
||||
|
@ -346,13 +351,13 @@ fn main() {
|
|||
~~~
|
||||
|
||||
This prints `5.83095189`. You can see that the `compute_distance` function
|
||||
takes in two borrowed pointers, but we give it a managed and unique pointer. Of
|
||||
takes in two references, but we give it a managed and unique pointer. Of
|
||||
course, if this were a real program, we wouldn't have any of these pointers,
|
||||
they're just there to demonstrate the concepts.
|
||||
|
||||
So how is this hard? Well, because we're igorning ownership, the compiler needs
|
||||
So how is this hard? Well, because we're ignoring ownership, the compiler needs
|
||||
to take great care to make sure that everything is safe. Despite their complete
|
||||
safety, a borrowed pointer's representation at runtime is the same as that of
|
||||
safety, a reference's representation at runtime is the same as that of
|
||||
an ordinary pointer in a C program. They introduce zero overhead. The compiler
|
||||
does all safety checks at compile time.
|
||||
|
||||
|
@ -360,14 +365,14 @@ This theory is called 'region pointers,' and involve a concept called
|
|||
'lifetimes'. Here's the simple explanation: would you expect this code to
|
||||
compile?
|
||||
|
||||
~~~rust {.xfail-test}
|
||||
~~~rust{.xfail-test}
|
||||
fn main() {
|
||||
println(x.to_str());
|
||||
let x = 5;
|
||||
}
|
||||
~~~
|
||||
|
||||
Probably not. That's becuase you know that the name `x` is valid from where
|
||||
Probably not. That's because you know that the name `x` is valid from where
|
||||
it's declared to when it goes out of scope. In this case, that's the end of
|
||||
the `main` function. So you know this code will cause an error. We call this
|
||||
duration a 'lifetime'. Let's try a more complex example:
|
||||
|
@ -375,12 +380,12 @@ duration a 'lifetime'. Let's try a more complex example:
|
|||
~~~rust
|
||||
fn main() {
|
||||
let mut x = ~5;
|
||||
if(*x < 10) {
|
||||
if *x < 10 {
|
||||
let y = &x;
|
||||
println!("Oh no: {:?}", y);
|
||||
return;
|
||||
}
|
||||
*x = *x - 1;
|
||||
*x -= 1;
|
||||
println!("Oh no: {:?}", x);
|
||||
}
|
||||
~~~
|
||||
|
@ -389,17 +394,17 @@ Here, we're borrowing a pointer to `x` inside of the `if`. The compiler, however
|
|||
is able to determine that that pointer will go out of scope without `x` being
|
||||
mutated, and therefore, lets us pass. This wouldn't work:
|
||||
|
||||
~~~rust {.xfail-test}
|
||||
~~~rust{.xfail-test}
|
||||
fn main() {
|
||||
let mut x = ~5;
|
||||
if(*x < 10) {
|
||||
if *x < 10 {
|
||||
let y = &x;
|
||||
*x = *x - 1;
|
||||
*x -= 1;
|
||||
|
||||
println!("Oh no: {:?}", y);
|
||||
return;
|
||||
}
|
||||
*x = *x - 1;
|
||||
*x -= 1;
|
||||
println!("Oh no: {:?}", x);
|
||||
}
|
||||
~~~
|
||||
|
@ -408,7 +413,7 @@ It gives this error:
|
|||
|
||||
~~~ {.notrust}
|
||||
test.rs:5:8: 5:10 error: cannot assign to `*x` because it is borrowed
|
||||
test.rs:5 *x = *x - 1;
|
||||
test.rs:5 *x -= 1;
|
||||
^~
|
||||
test.rs:4:16: 4:18 note: borrow of `*x` occurs here
|
||||
test.rs:4 let y = &x;
|
||||
|
@ -416,13 +421,13 @@ test.rs:4 let y = &x;
|
|||
~~~
|
||||
|
||||
As you might guess, this kind of analysis is complex for a human, and therefore
|
||||
hard for a computer, too! There is an entire [tutorial devoted to borrowed
|
||||
pointers and lifetimes](tutorial-lifetimes.html) that goes into lifetimes in
|
||||
hard for a computer, too! There is an entire [guide devoted to references
|
||||
and lifetimes](guide-lifetimes.html) that goes into lifetimes in
|
||||
great detail, so if you want the full details, check that out.
|
||||
|
||||
# Returning Pointers
|
||||
|
||||
We've talked a lot about funtions that accept various kinds of pointers, but
|
||||
We've talked a lot about functions that accept various kinds of pointers, but
|
||||
what about returning them? Here's the rule of thumb: only return a unique or
|
||||
managed pointer if you were given one in the first place.
|
||||
|
||||
|
@ -469,8 +474,9 @@ fn main() {
|
|||
You may think that this gives us terrible performance: return a value and then
|
||||
immediately box it up?!?! Isn't that the worst of both worlds? Rust is smarter
|
||||
than that. There is no copy in this code. `main` allocates enough room for the
|
||||
`@int`, passes it into `foo` as `x`, and then `foo` writes the value into the
|
||||
new box. This writes the return value directly into the allocated box.
|
||||
`@int`, passes a pointer to that memory into `foo` as `x`, and then `foo` writes
|
||||
the value straight into that pointer. This writes the return value directly into
|
||||
the allocated box.
|
||||
|
||||
This is important enough that it bears repeating: pointers are not for optimizing
|
||||
returning values from your code. Allow the caller to choose how they want to
|
||||
|
@ -479,4 +485,4 @@ use your output.
|
|||
|
||||
# Related Resources
|
||||
|
||||
* [Lifetimes tutorial](tutorial-lifetimes.html)
|
||||
* [Lifetimes guide](guide-lifetimes.html)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% Rust Packaging Guide
|
||||
% The Rust Packaging Guide
|
||||
|
||||
# Introduction
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% Rust Tasks and Communication Guide
|
||||
% The Rust Tasks and Communication Guide
|
||||
|
||||
# Introduction
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
% Rust Testing Guide
|
||||
% The Rust Testing Guide
|
||||
|
||||
# Quick start
|
||||
|
||||
To create test functions, add a `#[test]` attribute like this:
|
||||
|
||||
```rust
|
||||
~~~
|
||||
fn return_two() -> int {
|
||||
2
|
||||
}
|
||||
|
@ -14,17 +14,17 @@ fn return_two_test() {
|
|||
let x = return_two();
|
||||
assert!(x == 2);
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
To run these tests, use `rustc --test`:
|
||||
|
||||
```
|
||||
~~~ {.notrust}
|
||||
$ rustc --test foo.rs; ./foo
|
||||
running 1 test
|
||||
test return_two_test ... ok
|
||||
|
||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
|
||||
```
|
||||
~~~
|
||||
|
||||
`rustc foo.rs` will *not* compile the tests, since `#[test]` implies
|
||||
`#[cfg(test)]`. The `--test` flag to `rustc` implies `--cfg test`.
|
||||
|
@ -35,12 +35,12 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
|
|||
Rust has built in support for simple unit testing. Functions can be
|
||||
marked as unit tests using the 'test' attribute.
|
||||
|
||||
```rust
|
||||
~~~
|
||||
#[test]
|
||||
fn return_none_if_empty() {
|
||||
// ... test code ...
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
A test function's signature must have no arguments and no return
|
||||
value. To run the tests in a crate, it must be compiled with the
|
||||
|
@ -54,7 +54,7 @@ then the test fails.
|
|||
When compiling a crate with the '--test' flag '--cfg test' is also
|
||||
implied, so that tests can be conditionally compiled.
|
||||
|
||||
```rust
|
||||
~~~
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
|
@ -62,7 +62,7 @@ mod tests {
|
|||
// ... test code ...
|
||||
}
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
Additionally #[test] items behave as if they also have the
|
||||
#[cfg(test)] attribute, and will not be compiled when the --test flag
|
||||
|
@ -79,14 +79,14 @@ Tests that are intended to fail can be annotated with the
|
|||
task to fail then the test will be counted as successful; otherwise it
|
||||
will be counted as a failure. For example:
|
||||
|
||||
```rust
|
||||
~~~
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_out_of_bounds_failure() {
|
||||
let v: [int] = [];
|
||||
v[0];
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
A test runner built with the '--test' flag supports a limited set of
|
||||
arguments to control which tests are run: the first free argument
|
||||
|
@ -126,7 +126,7 @@ amount.
|
|||
|
||||
For example:
|
||||
|
||||
```rust
|
||||
~~~
|
||||
extern mod extra;
|
||||
use std::vec;
|
||||
|
||||
|
@ -141,7 +141,7 @@ fn initialise_a_vector(b: &mut extra::test::BenchHarness) {
|
|||
b.iter(|| {vec::from_elem(1024, 0u64);} );
|
||||
b.bytes = 1024 * 8;
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
The benchmark runner will calibrate measurement of the benchmark
|
||||
function to run the `iter` block "enough" times to get a reliable
|
||||
|
@ -168,7 +168,7 @@ test-runner. Benchmarks are compiled-in but not executed by default.
|
|||
|
||||
### Typical test run
|
||||
|
||||
```
|
||||
~~~ {.notrust}
|
||||
> mytests
|
||||
|
||||
running 30 tests
|
||||
|
@ -178,11 +178,11 @@ running driver::tests::mytest2 ... ignored
|
|||
running driver::tests::mytest30 ... ok
|
||||
|
||||
result: ok. 28 passed; 0 failed; 2 ignored
|
||||
```
|
||||
~~~ {.notrust}
|
||||
|
||||
### Test run with failures
|
||||
|
||||
```
|
||||
~~~ {.notrust}
|
||||
> mytests
|
||||
|
||||
running 30 tests
|
||||
|
@ -192,11 +192,11 @@ running driver::tests::mytest2 ... ignored
|
|||
running driver::tests::mytest30 ... FAILED
|
||||
|
||||
result: FAILED. 27 passed; 1 failed; 2 ignored
|
||||
```
|
||||
~~~
|
||||
|
||||
### Running ignored tests
|
||||
|
||||
```
|
||||
~~~ {.notrust}
|
||||
> mytests --ignored
|
||||
|
||||
running 2 tests
|
||||
|
@ -204,11 +204,11 @@ running driver::tests::mytest2 ... failed
|
|||
running driver::tests::mytest10 ... ok
|
||||
|
||||
result: FAILED. 1 passed; 1 failed; 0 ignored
|
||||
```
|
||||
~~~
|
||||
|
||||
### Running a subset of tests
|
||||
|
||||
```
|
||||
~~~ {.notrust}
|
||||
> mytests mytest1
|
||||
|
||||
running 11 tests
|
||||
|
@ -218,11 +218,11 @@ running driver::tests::mytest10 ... ignored
|
|||
running driver::tests::mytest19 ... ok
|
||||
|
||||
result: ok. 11 passed; 0 failed; 1 ignored
|
||||
```
|
||||
~~~
|
||||
|
||||
### Running benchmarks
|
||||
|
||||
```
|
||||
~~~ {.notrust}
|
||||
> mytests --bench
|
||||
|
||||
running 2 tests
|
||||
|
@ -230,7 +230,7 @@ test bench_sum_1024_ints ... bench: 709 ns/iter (+/- 82)
|
|||
test initialise_a_vector ... bench: 424 ns/iter (+/- 99) = 19320 MB/s
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured
|
||||
```
|
||||
~~~
|
||||
|
||||
## Saving and ratcheting metrics
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# Guides
|
||||
|
||||
[Pointers](guide-pointers.html)
|
||||
[Lifetimes](guide-lifetimes.html)
|
||||
[References and Lifetimes](guide-lifetimes.html)
|
||||
[Containers and Iterators](guide-container.html)
|
||||
[Tasks and Communication](guide-tasks.html)
|
||||
[Foreign Function Interface](guide-ffi.html)
|
||||
|
@ -24,7 +24,11 @@
|
|||
# Libraries
|
||||
|
||||
[std](std/index.html)
|
||||
[extra](index.html)
|
||||
[extra](extra/index.html)
|
||||
[green](green/index.html)
|
||||
[native](native/index.html)
|
||||
[syntax](syntax/index.html)
|
||||
[rustc](rustc/index.html)
|
||||
|
||||
# Tooling
|
||||
|
||||
|
|
44
doc/rust.md
44
doc/rust.md
|
@ -1,4 +1,4 @@
|
|||
% Rust Reference Manual
|
||||
% The Rust Reference Manual
|
||||
|
||||
# Introduction
|
||||
|
||||
|
@ -1215,7 +1215,7 @@ A static item must have a _constant expression_ giving its definition.
|
|||
|
||||
Static items must be explicitly typed.
|
||||
The type may be ```bool```, ```char```, a number, or a type derived from those primitive types.
|
||||
The derived types are borrowed pointers with the `'static` lifetime,
|
||||
The derived types are references with the `'static` lifetime,
|
||||
fixed-size arrays, tuples, and structs.
|
||||
|
||||
~~~~
|
||||
|
@ -1841,7 +1841,7 @@ A complete list of the built-in language items follows:
|
|||
`owned`
|
||||
: Are uniquely owned.
|
||||
`durable`
|
||||
: Contain borrowed pointers.
|
||||
: Contain references.
|
||||
`drop`
|
||||
: Have finalizers.
|
||||
`add`
|
||||
|
@ -1898,11 +1898,11 @@ A complete list of the built-in language items follows:
|
|||
`free`
|
||||
: Free memory that was allocated on the managed heap.
|
||||
`borrow_as_imm`
|
||||
: Create an immutable borrowed pointer to a mutable value.
|
||||
: Create an immutable reference to a mutable value.
|
||||
`return_to_mut`
|
||||
: Release a borrowed pointer created with `return_to_mut`
|
||||
: Release a reference created with `return_to_mut`
|
||||
`check_not_borrowed`
|
||||
: Fail if a value has existing borrowed pointers to it.
|
||||
: Fail if a value has existing references to it.
|
||||
`strdup_uniq`
|
||||
: Return a new unique string
|
||||
containing a copy of the contents of a unique string.
|
||||
|
@ -2199,7 +2199,7 @@ When an lvalue is evaluated in an _lvalue context_, it denotes a memory location
|
|||
when evaluated in an _rvalue context_, it denotes the value held _in_ that memory location.
|
||||
|
||||
When an rvalue is used in lvalue context, a temporary un-named lvalue is created and used instead.
|
||||
A temporary's lifetime equals the largest lifetime of any borrowed pointer that points to it.
|
||||
A temporary's lifetime equals the largest lifetime of any reference that points to it.
|
||||
|
||||
#### Moved and copied types
|
||||
|
||||
|
@ -2403,8 +2403,8 @@ before the expression they apply to.
|
|||
: [Boxing](#pointer-types) operators. Allocate a box to hold the value they are applied to,
|
||||
and store the value in it. `@` creates a managed box, whereas `~` creates an owned box.
|
||||
`&`
|
||||
: Borrow operator. Returns a borrowed pointer, pointing to its operand.
|
||||
The operand of a borrowed pointer is statically proven to outlive the resulting pointer.
|
||||
: Borrow operator. Returns a reference, pointing to its operand.
|
||||
The operand of a borrow is statically proven to outlive the resulting pointer.
|
||||
If the borrow-checker cannot prove this, it is a compilation error.
|
||||
|
||||
### Binary operator expressions
|
||||
|
@ -2894,9 +2894,9 @@ match x {
|
|||
Patterns that bind variables
|
||||
default to binding to a copy or move of the matched value
|
||||
(depending on the matched value's type).
|
||||
This can be changed to bind to a borrowed pointer by
|
||||
This can be changed to bind to a reference by
|
||||
using the ```ref``` keyword,
|
||||
or to a mutable borrowed pointer using ```ref mut```.
|
||||
or to a mutable reference using ```ref mut```.
|
||||
|
||||
A pattern that's just an identifier,
|
||||
like `Nil` in the previous answer,
|
||||
|
@ -3172,18 +3172,18 @@ Owning pointers (`~`)
|
|||
it involves allocating a new owned box and copying the contents of the old box into the new box.
|
||||
Releasing an owning pointer immediately releases its corresponding owned box.
|
||||
|
||||
Borrowed pointers (`&`)
|
||||
References (`&`)
|
||||
: These point to memory _owned by some other value_.
|
||||
Borrowed pointers arise by (automatic) conversion from owning pointers, managed pointers,
|
||||
References arise by (automatic) conversion from owning pointers, managed pointers,
|
||||
or by applying the borrowing operator `&` to some other value,
|
||||
including [lvalues, rvalues or temporaries](#lvalues-rvalues-and-temporaries).
|
||||
Borrowed pointers are written `&content`, or in some cases `&'f content` for some lifetime-variable `f`,
|
||||
for example `&int` means a borrowed pointer to an integer.
|
||||
Copying a borrowed pointer is a "shallow" operation:
|
||||
References are written `&content`, or in some cases `&'f content` for some lifetime-variable `f`,
|
||||
for example `&int` means a reference to an integer.
|
||||
Copying a reference is a "shallow" operation:
|
||||
it involves only copying the pointer itself.
|
||||
Releasing a borrowed pointer typically has no effect on the value it points to,
|
||||
Releasing a reference typically has no effect on the value it points to,
|
||||
with the exception of temporary values,
|
||||
which are released when the last borrowed pointer to them is released.
|
||||
which are released when the last reference to them is released.
|
||||
|
||||
Raw pointers (`*`)
|
||||
: Raw pointers are pointers without safety or liveness guarantees.
|
||||
|
@ -3338,7 +3338,7 @@ The kinds are:
|
|||
This kind includes scalars and immutable references,
|
||||
as well as structural types containing other `Pod` types.
|
||||
`'static`
|
||||
: Types of this kind do not contain any borrowed pointers;
|
||||
: Types of this kind do not contain any references;
|
||||
this can be a useful guarantee for code
|
||||
that breaks borrowing assumptions
|
||||
using [`unsafe` operations](#unsafe-functions).
|
||||
|
@ -3417,14 +3417,14 @@ frame they are allocated within.
|
|||
### Memory ownership
|
||||
|
||||
A task owns all memory it can *safely* reach through local variables,
|
||||
as well as managed, owning and borrowed pointers.
|
||||
as well as managed, owned boxes and references.
|
||||
|
||||
When a task sends a value that has the `Send` trait to another task,
|
||||
it loses ownership of the value sent and can no longer refer to it.
|
||||
This is statically guaranteed by the combined use of "move semantics",
|
||||
and the compiler-checked _meaning_ of the `Send` trait:
|
||||
it is only instantiated for (transitively) sendable kinds of data constructor and pointers,
|
||||
never including managed or borrowed pointers.
|
||||
never including managed boxes or references.
|
||||
|
||||
When a stack frame is exited, its local allocations are all released, and its
|
||||
references to boxes (both managed and owned) are dropped.
|
||||
|
@ -3569,7 +3569,7 @@ These include:
|
|||
- simple locks and semaphores
|
||||
|
||||
When such facilities carry values, the values are restricted to the [`Send` type-kind](#type-kinds).
|
||||
Restricting communication interfaces to this kind ensures that no borrowed or managed pointers move between tasks.
|
||||
Restricting communication interfaces to this kind ensures that no references or managed pointers move between tasks.
|
||||
Thus access to an entire data structure can be mediated through its owning "root" value;
|
||||
no further locking or copying is required to avoid data races within the substructure of such a value.
|
||||
|
||||
|
|
|
@ -1341,11 +1341,12 @@ let mut y = ~5; // mutable
|
|||
*y += 2; // the * operator is needed to access the contained value
|
||||
~~~~
|
||||
|
||||
# Borrowed pointers
|
||||
# References
|
||||
|
||||
Rust's borrowed pointers are a general purpose reference type. In contrast with
|
||||
In contrast with
|
||||
owned boxes, where the holder of an owned box is the owner of the pointed-to
|
||||
memory, borrowed pointers never imply ownership. A pointer can be borrowed to
|
||||
memory, references never imply ownership - they are "borrowed".
|
||||
A reference can be borrowed to
|
||||
any object, and the compiler verifies that it cannot outlive the lifetime of
|
||||
the object.
|
||||
|
||||
|
@ -1377,7 +1378,7 @@ to define a function that takes two arguments of type point—that is,
|
|||
it takes the points by value. But this will cause the points to be
|
||||
copied when we call the function. For points, this is probably not so
|
||||
bad, but often copies are expensive. So we’d like to define a function
|
||||
that takes the points by pointer. We can use borrowed pointers to do this:
|
||||
that takes the points by pointer. We can use references to do this:
|
||||
|
||||
~~~
|
||||
# struct Point { x: f64, y: f64 }
|
||||
|
@ -1410,7 +1411,7 @@ route to the same data.
|
|||
|
||||
In the case of the boxes `managed_box` and `owned_box`, however, no
|
||||
explicit action is necessary. The compiler will automatically convert
|
||||
a box like `@point` or `~point` to a borrowed pointer like
|
||||
a box like `@point` or `~point` to a reference like
|
||||
`&point`. This is another form of borrowing; in this case, the
|
||||
contents of the managed/owned box are being lent out.
|
||||
|
||||
|
@ -1420,11 +1421,11 @@ have been lent out, you cannot send that variable to another task, nor
|
|||
will you be permitted to take actions that might cause the borrowed
|
||||
value to be freed or to change its type. This rule should make
|
||||
intuitive sense: you must wait for a borrowed value to be returned
|
||||
(that is, for the borrowed pointer to go out of scope) before you can
|
||||
(that is, for the reference to go out of scope) before you can
|
||||
make full use of it again.
|
||||
|
||||
For a more in-depth explanation of borrowed pointers and lifetimes, read the
|
||||
[lifetimes and borrowed pointer tutorial][lifetimes].
|
||||
For a more in-depth explanation of references and lifetimes, read the
|
||||
[references and lifetimes guide][lifetimes].
|
||||
|
||||
## Freezing
|
||||
|
||||
|
@ -1622,8 +1623,7 @@ defined in [`std::vec`] and [`std::str`].
|
|||
|
||||
# Ownership escape hatches
|
||||
|
||||
Ownership can cleanly describe tree-like data structures, and borrowed pointers provide non-owning
|
||||
references. However, more flexibility is often desired and Rust provides ways to escape from strict
|
||||
Ownership can cleanly describe tree-like data structures, and references provide non-owning pointers. However, more flexibility is often desired and Rust provides ways to escape from strict
|
||||
single parent ownership.
|
||||
|
||||
The standard library provides the `std::rc::Rc` pointer type to express *shared ownership* over a
|
||||
|
@ -1880,7 +1880,7 @@ A caller must in turn have a compatible pointer type to call the method.
|
|||
# Rectangle(Point, Point)
|
||||
# }
|
||||
impl Shape {
|
||||
fn draw_borrowed(&self) { ... }
|
||||
fn draw_reference(&self) { ... }
|
||||
fn draw_managed(@self) { ... }
|
||||
fn draw_owned(~self) { ... }
|
||||
fn draw_value(self) { ... }
|
||||
|
@ -1890,13 +1890,13 @@ let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
|
|||
|
||||
(@s).draw_managed();
|
||||
(~s).draw_owned();
|
||||
(&s).draw_borrowed();
|
||||
(&s).draw_reference();
|
||||
s.draw_value();
|
||||
~~~
|
||||
|
||||
Methods typically take a borrowed pointer self type,
|
||||
Methods typically take a reference self type,
|
||||
so the compiler will go to great lengths to convert a callee
|
||||
to a borrowed pointer.
|
||||
to a reference.
|
||||
|
||||
~~~
|
||||
# fn draw_circle(p: Point, f: f64) { }
|
||||
|
@ -1907,27 +1907,27 @@ to a borrowed pointer.
|
|||
# Rectangle(Point, Point)
|
||||
# }
|
||||
# impl Shape {
|
||||
# fn draw_borrowed(&self) { ... }
|
||||
# fn draw_reference(&self) { ... }
|
||||
# fn draw_managed(@self) { ... }
|
||||
# fn draw_owned(~self) { ... }
|
||||
# fn draw_value(self) { ... }
|
||||
# }
|
||||
# let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
|
||||
// As with typical function arguments, managed and owned pointers
|
||||
// are automatically converted to borrowed pointers
|
||||
// are automatically converted to references
|
||||
|
||||
(@s).draw_borrowed();
|
||||
(~s).draw_borrowed();
|
||||
(@s).draw_reference();
|
||||
(~s).draw_reference();
|
||||
|
||||
// Unlike typical function arguments, the self value will
|
||||
// automatically be referenced ...
|
||||
s.draw_borrowed();
|
||||
s.draw_reference();
|
||||
|
||||
// ... and dereferenced
|
||||
(& &s).draw_borrowed();
|
||||
(& &s).draw_reference();
|
||||
|
||||
// ... and dereferenced and borrowed
|
||||
(&@~s).draw_borrowed();
|
||||
(&@~s).draw_reference();
|
||||
~~~
|
||||
|
||||
Implementations may also define standalone (sometimes called "static")
|
||||
|
@ -2095,7 +2095,7 @@ and may not be overridden:
|
|||
|
||||
* `Send` - Sendable types.
|
||||
Types are sendable
|
||||
unless they contain managed boxes, managed closures, or borrowed pointers.
|
||||
unless they contain managed boxes, managed closures, or references.
|
||||
|
||||
* `Freeze` - Constant (immutable) types.
|
||||
These are types that do not contain anything intrinsically mutable.
|
||||
|
@ -2104,7 +2104,7 @@ Intrinsically mutable values include `Cell` in the standard library.
|
|||
* `'static` - Non-borrowed types.
|
||||
These are types that do not contain any data whose lifetime is bound to
|
||||
a particular stack frame. These are types that do not contain any
|
||||
borrowed pointers, or types where the only contained borrowed pointers
|
||||
references, or types where the only contained references
|
||||
have the `'static` lifetime.
|
||||
|
||||
> ***Note:*** These two traits were referred to as 'kinds' in earlier
|
||||
|
@ -2439,7 +2439,7 @@ order to be packaged up in a trait object of that storage class.
|
|||
|
||||
* The contents of owned traits (`~Trait`) must fulfill the `Send` bound.
|
||||
* The contents of managed traits (`@Trait`) must fulfill the `'static` bound.
|
||||
* The contents of borrowed traits (`&Trait`) are not constrained by any bound.
|
||||
* The contents of reference traits (`&Trait`) are not constrained by any bound.
|
||||
|
||||
Consequently, the trait objects themselves automatically fulfill their
|
||||
respective kind bounds. However, this default behavior can be overridden by
|
||||
|
|
|
@ -22,6 +22,7 @@ TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
|
|||
# Markdown files under doc/ that should have their code extracted and run
|
||||
DOC_TEST_NAMES = tutorial guide-ffi guide-macros guide-lifetimes \
|
||||
guide-tasks guide-conditions guide-container guide-pointers \
|
||||
complement-cheatsheet \
|
||||
rust
|
||||
|
||||
######################################################################
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#define CFG_VERSION GetEnv("CFG_VERSION")
|
||||
#define CFG_VERSION_WIN GetEnv("CFG_VERSION_WIN")
|
||||
#define CFG_RELEASE GetEnv("CFG_RELEASE")
|
||||
|
||||
[Setup]
|
||||
|
||||
|
@ -19,7 +20,7 @@ DisableStartupPrompt=true
|
|||
|
||||
OutputDir=.\
|
||||
SourceDir=.\
|
||||
OutputBaseFilename=rust-{#CFG_VERSION}-install
|
||||
OutputBaseFilename=rust-{#CFG_RELEASE}-install
|
||||
DefaultDirName={pf32}\Rust
|
||||
|
||||
Compression=lzma2/ultra
|
||||
|
|
|
@ -60,8 +60,8 @@ impl<A> Future<A> {
|
|||
|
||||
pub fn get_ref<'a>(&'a mut self) -> &'a A {
|
||||
/*!
|
||||
* Executes the future's closure and then returns a borrowed
|
||||
* pointer to the result. The borrowed pointer lasts as long as
|
||||
* Executes the future's closure and then returns a reference
|
||||
* to the result. The reference lasts as long as
|
||||
* the future.
|
||||
*/
|
||||
match self.state {
|
||||
|
|
|
@ -431,7 +431,7 @@ struct RWLockInner {
|
|||
// (or reader/downgrader) race.
|
||||
// By the way, if we didn't care about the assert in the read unlock path,
|
||||
// we could instead store the mode flag in write_downgrade's stack frame,
|
||||
// and have the downgrade tokens store a borrowed pointer to it.
|
||||
// and have the downgrade tokens store a reference to it.
|
||||
read_mode: bool,
|
||||
// The only way the count flag is ever accessed is with xadd. Since it is
|
||||
// a read-modify-write operation, multiple xadds on different cores will
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "rlib"];
|
||||
#[crate_type = "dylib"];
|
||||
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://static.rust-lang.org/doc/master")];
|
||||
|
||||
// NB this does *not* include globs, please keep it that way.
|
||||
#[feature(macro_rules)];
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "rlib"];
|
||||
#[crate_type = "dylib"];
|
||||
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://static.rust-lang.org/doc/master")];
|
||||
|
||||
// NB this crate explicitly does *not* allow glob imports, please seriously
|
||||
// consider whether they're needed before adding that feature here (the
|
||||
|
|
|
@ -8,11 +8,24 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/*!
|
||||
|
||||
The Rust compiler.
|
||||
|
||||
# Note
|
||||
|
||||
This API is completely unstable and subject to change.
|
||||
|
||||
*/
|
||||
|
||||
#[crate_id = "rustc#0.9"];
|
||||
#[comment = "The Rust compiler"];
|
||||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "dylib"];
|
||||
#[crate_type = "rlib"];
|
||||
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://static.rust-lang.org/doc/master")];
|
||||
|
||||
#[feature(macro_rules, globs, struct_variant, managed_boxes)];
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ referent).
|
|||
It then uses the dataflow module to propagate which of those borrows
|
||||
may be in scope at each point in the procedure. A loan is considered
|
||||
to come into scope at the expression that caused it and to go out of
|
||||
scope when the lifetime of the resulting borrowed pointer expires.
|
||||
scope when the lifetime of the resulting reference expires.
|
||||
|
||||
Once the in-scope loans are known for each point in the program, the
|
||||
borrow checker walks the IR again in a second pass called
|
||||
|
@ -146,14 +146,14 @@ result of the borrow `&mut (*x).f` in the example above:
|
|||
|
||||
The loan states that the expression `(*x).f` has been loaned as
|
||||
mutable for the lifetime `'a`. Because the loan is mutable, that means
|
||||
that the value `(*x).f` may be mutated via the newly created borrowed
|
||||
pointer (and *only* via that pointer). This is reflected in the
|
||||
that the value `(*x).f` may be mutated via the newly created reference
|
||||
(and *only* via that pointer). This is reflected in the
|
||||
restrictions `RS` that accompany the loan.
|
||||
|
||||
The first restriction `((*x).f, [MUTATE, CLAIM, FREEZE])` states that
|
||||
the lender may not mutate nor freeze `(*x).f`. Mutation is illegal
|
||||
because `(*x).f` is only supposed to be mutated via the new borrowed
|
||||
pointer, not by mutating the original path `(*x).f`. Freezing is
|
||||
because `(*x).f` is only supposed to be mutated via the new reference,
|
||||
not by mutating the original path `(*x).f`. Freezing is
|
||||
illegal because the path now has an `&mut` alias; so even if we the
|
||||
lender were to consider `(*x).f` to be immutable, it might be mutated
|
||||
via this alias. Both of these restrictions are temporary. They will be
|
||||
|
@ -164,8 +164,8 @@ The second restriction on `*x` is interesting because it does not
|
|||
apply to the path that was lent (`(*x).f`) but rather to a prefix of
|
||||
the borrowed path. This is due to the rules of inherited mutability:
|
||||
if the user were to assign to (or freeze) `*x`, they would indirectly
|
||||
overwrite (or freeze) `(*x).f`, and thus invalidate the borrowed
|
||||
pointer that was created. In general it holds that when a path is
|
||||
overwrite (or freeze) `(*x).f`, and thus invalidate the reference
|
||||
that was created. In general it holds that when a path is
|
||||
lent, restrictions are issued for all the owning prefixes of that
|
||||
path. In this case, the path `*x` owns the path `(*x).f` and,
|
||||
because `x` is an owned pointer, the path `x` owns the path `*x`.
|
||||
|
@ -241,7 +241,7 @@ lvalue `LV` being borrowed and the mutability `MQ` and lifetime `LT`
|
|||
of the resulting pointer. Given those, `gather_loans` applies three
|
||||
validity tests:
|
||||
|
||||
1. `MUTABILITY(LV, MQ)`: The mutability of the borrowed pointer is
|
||||
1. `MUTABILITY(LV, MQ)`: The mutability of the reference is
|
||||
compatible with the mutability of `LV` (i.e., not borrowing immutable
|
||||
data as mutable).
|
||||
|
||||
|
@ -380,9 +380,9 @@ of its owner:
|
|||
TYPE(LV) = ~Ty
|
||||
LIFETIME(LV, LT, MQ)
|
||||
|
||||
### Checking lifetime for derefs of borrowed pointers
|
||||
### Checking lifetime for derefs of references
|
||||
|
||||
Borrowed pointers have a lifetime `LT'` associated with them. The
|
||||
References have a lifetime `LT'` associated with them. The
|
||||
data they point at has been guaranteed to be valid for at least this
|
||||
lifetime. Therefore, the borrow is valid so long as the lifetime `LT`
|
||||
of the borrow is shorter than the lifetime `LT'` of the pointer
|
||||
|
@ -412,7 +412,7 @@ value is not mutated or moved. Note that lvalues are either
|
|||
(ultimately) owned by a local variable, in which case we can check
|
||||
whether that local variable is ever moved in its scope, or they are
|
||||
owned by the referent of an (immutable, due to condition 2) managed or
|
||||
borrowed pointer, in which case moves are not permitted because the
|
||||
references, in which case moves are not permitted because the
|
||||
location is aliasable.
|
||||
|
||||
If the conditions of `L-Deref-Managed-Imm-User-Root` are not met, then
|
||||
|
|
|
@ -662,7 +662,7 @@ impl<'a> GatherLoanCtxt<'a> {
|
|||
//! &mut v.counter
|
||||
//! }
|
||||
//!
|
||||
//! In this case, the borrowed pointer (`'a`) outlives the
|
||||
//! In this case, the reference (`'a`) outlives the
|
||||
//! variable `v` that hosts it. Note that this doesn't come up
|
||||
//! with immutable `&` pointers, because borrows of such pointers
|
||||
//! do not require restrictions and hence do not cause a loan.
|
||||
|
|
|
@ -719,7 +719,7 @@ impl BorrowckCtxt {
|
|||
err_out_of_scope(super_scope, sub_scope) => {
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
"borrowed pointer must be valid for ",
|
||||
"reference must be valid for ",
|
||||
sub_scope,
|
||||
"...");
|
||||
note_and_explain_region(
|
||||
|
|
|
@ -192,7 +192,7 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
|
|||
ExprAddrOf(..) => {
|
||||
sess.span_err(
|
||||
e.span,
|
||||
"borrowed pointers in constants may only refer to \
|
||||
"references in constants may only refer to \
|
||||
immutable values");
|
||||
},
|
||||
ExprVstore(_, ExprVstoreUniq) |
|
||||
|
|
|
@ -33,7 +33,7 @@ use syntax::visit::Visitor;
|
|||
// send: Things that can be sent on channels or included in spawned closures.
|
||||
// freeze: Things thare are deeply immutable. They are guaranteed never to
|
||||
// change, and can be safely shared without copying between tasks.
|
||||
// 'static: Things that do not contain borrowed pointers.
|
||||
// 'static: Things that do not contain references.
|
||||
//
|
||||
// Send includes scalar types as well as classes and unique types containing
|
||||
// only sendable types.
|
||||
|
@ -487,12 +487,11 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: Span) -> bool {
|
|||
if !ty::type_is_static(tcx, ty) {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_param(..) => {
|
||||
tcx.sess.span_err(sp, "value may contain borrowed \
|
||||
pointers; add `'static` bound");
|
||||
tcx.sess.span_err(sp, "value may contain references; \
|
||||
add `'static` bound");
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_err(sp, "value may contain borrowed \
|
||||
pointers");
|
||||
tcx.sess.span_err(sp, "value may contain references");
|
||||
}
|
||||
}
|
||||
false
|
||||
|
@ -502,10 +501,10 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: Span) -> bool {
|
|||
}
|
||||
|
||||
/// This is rather subtle. When we are casting a value to a instantiated
|
||||
/// trait like `a as trait<'r>`, regionck already ensures that any borrowed
|
||||
/// pointers that appear in the type of `a` are bounded by `'r` (ed.: rem
|
||||
/// trait like `a as trait<'r>`, regionck already ensures that any references
|
||||
/// that appear in the type of `a` are bounded by `'r` (ed.: rem
|
||||
/// FIXME(#5723)). However, it is possible that there are *type parameters*
|
||||
/// in the type of `a`, and those *type parameters* may have borrowed pointers
|
||||
/// in the type of `a`, and those *type parameters* may have references
|
||||
/// within them. We have to guarantee that the regions which appear in those
|
||||
/// type parameters are not obscured.
|
||||
///
|
||||
|
@ -513,17 +512,17 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: Span) -> bool {
|
|||
///
|
||||
/// (1) The trait instance cannot escape the current fn. This is
|
||||
/// guaranteed if the region bound `&r` is some scope within the fn
|
||||
/// itself. This case is safe because whatever borrowed pointers are
|
||||
/// itself. This case is safe because whatever references are
|
||||
/// found within the type parameter, they must enclose the fn body
|
||||
/// itself.
|
||||
///
|
||||
/// (2) The type parameter appears in the type of the trait. For
|
||||
/// example, if the type parameter is `T` and the trait type is
|
||||
/// `deque<T>`, then whatever borrowed ptrs may appear in `T` also
|
||||
/// `deque<T>`, then whatever references may appear in `T` also
|
||||
/// appear in `deque<T>`.
|
||||
///
|
||||
/// (3) The type parameter is sendable (and therefore does not contain
|
||||
/// borrowed ptrs).
|
||||
/// references).
|
||||
///
|
||||
/// FIXME(#5723)---This code should probably move into regionck.
|
||||
pub fn check_cast_for_escaping_regions(
|
||||
|
@ -573,7 +572,7 @@ pub fn check_cast_for_escaping_regions(
|
|||
// if !target_regions.iter().any(|t_r| is_subregion_of(cx, *t_r, r)) {
|
||||
// cx.tcx.sess.span_err(
|
||||
// source_span,
|
||||
// format!("source contains borrowed pointer with lifetime \
|
||||
// format!("source contains reference with lifetime \
|
||||
// not found in the target type `{}`",
|
||||
// ty_to_str(cx.tcx, target_ty)));
|
||||
// note_and_explain_region(
|
||||
|
|
|
@ -612,7 +612,7 @@ impl VisitContext {
|
|||
self.use_receiver(receiver_expr);
|
||||
|
||||
// for overloaded operatrs, we are always passing in a
|
||||
// borrowed pointer, so it's always read mode:
|
||||
// reference, so it's always read mode:
|
||||
for arg_expr in arg_exprs.iter() {
|
||||
self.use_expr(*arg_expr, Read);
|
||||
}
|
||||
|
|
|
@ -1752,7 +1752,7 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
|
|||
* think of them as kind of an "anti-kind". They track the kinds of values
|
||||
* and thinks that are contained in types. Having a larger contents for
|
||||
* a type tends to rule that type *out* from various kinds. For example,
|
||||
* a type that contains a borrowed pointer is not sendable.
|
||||
* a type that contains a reference is not sendable.
|
||||
*
|
||||
* The reason we compute type contents and not kinds is that it is
|
||||
* easier for me (nmatsakis) to think about what is contained within
|
||||
|
@ -2188,7 +2188,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
|
|||
mutbl: ast::Mutability)
|
||||
-> TypeContents {
|
||||
/*!
|
||||
* Type contents due to containing a borrowed pointer
|
||||
* Type contents due to containing a reference
|
||||
* with the region `region` and borrow kind `bk`
|
||||
*/
|
||||
|
||||
|
|
|
@ -789,10 +789,10 @@ fn constrain_regions_in_type(
|
|||
pub mod guarantor {
|
||||
/*!
|
||||
* The routines in this module are aiming to deal with the case
|
||||
* where a the contents of a borrowed pointer are re-borrowed.
|
||||
* Imagine you have a borrowed pointer `b` with lifetime L1 and
|
||||
* where a the contents of a reference are re-borrowed.
|
||||
* Imagine you have a reference `b` with lifetime L1 and
|
||||
* you have an expression `&*b`. The result of this borrow will
|
||||
* be another borrowed pointer with lifetime L2 (which is an
|
||||
* be another reference with lifetime L2 (which is an
|
||||
* inference variable). The borrow checker is going to enforce
|
||||
* the constraint that L2 < L1, because otherwise you are
|
||||
* re-borrowing data for a lifetime larger than the original loan.
|
||||
|
@ -815,15 +815,15 @@ pub mod guarantor {
|
|||
* a borrow.
|
||||
*
|
||||
* The key point here is that when you are borrowing a value that
|
||||
* is "guaranteed" by a borrowed pointer, you must link the
|
||||
* lifetime of that borrowed pointer (L1, here) to the lifetime of
|
||||
* is "guaranteed" by a reference, you must link the
|
||||
* lifetime of that reference (L1, here) to the lifetime of
|
||||
* the borrow itself (L2). What do I mean by "guaranteed" by a
|
||||
* borrowed pointer? I mean any data that is reached by first
|
||||
* dereferencing a borrowed pointer and then either traversing
|
||||
* reference? I mean any data that is reached by first
|
||||
* dereferencing a reference and then either traversing
|
||||
* interior offsets or owned pointers. We say that the guarantor
|
||||
* of such data it the region of the borrowed pointer that was
|
||||
* of such data it the region of the reference that was
|
||||
* traversed. This is essentially the same as the ownership
|
||||
* relation, except that a borrowed pointer never owns its
|
||||
* relation, except that a reference never owns its
|
||||
* contents.
|
||||
*
|
||||
* NB: I really wanted to use the `mem_categorization` code here
|
||||
|
@ -953,7 +953,7 @@ pub mod guarantor {
|
|||
guarantor: Option<ty::Region>) {
|
||||
/*!
|
||||
*
|
||||
* Links the lifetime of the borrowed pointer resulting from a borrow
|
||||
* Links the lifetime of the reference resulting from a borrow
|
||||
* to the lifetime of its guarantor (if any).
|
||||
*/
|
||||
|
||||
|
@ -1134,7 +1134,7 @@ pub mod guarantor {
|
|||
Some(ty::AutoBorrowFn(r)) |
|
||||
Some(ty::AutoBorrowObj(r, _)) => {
|
||||
// If there is an autoref, then the result of this
|
||||
// expression will be some sort of borrowed pointer.
|
||||
// expression will be some sort of reference.
|
||||
expr_ct.cat.guarantor = None;
|
||||
expr_ct.cat.pointer = BorrowedPointer(r);
|
||||
debug!("autoref, cat={:?}", expr_ct.cat);
|
||||
|
|
|
@ -146,7 +146,7 @@ pub fn relate_free_regions(
|
|||
* for each function just before we check the body of that
|
||||
* function, looking for types where you have a borrowed
|
||||
* pointer to other borrowed data (e.g., `&'a &'b [uint]`.
|
||||
* We do not allow borrowed pointers to outlive the things they
|
||||
* We do not allow references to outlive the things they
|
||||
* point at, so we can assume that `'a <= 'b`.
|
||||
*
|
||||
* Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
|
||||
|
|
|
@ -20,8 +20,8 @@ but not in representation (so actual subtyping is inappropriate).
|
|||
|
||||
## Reborrowing
|
||||
|
||||
Note that if we are expecting a borrowed pointer, we will *reborrow*
|
||||
even if the argument provided was already a borrowed pointer. This is
|
||||
Note that if we are expecting a reference, we will *reborrow*
|
||||
even if the argument provided was already a reference. This is
|
||||
useful for freezing mut/const things (that is, when the expected is &T
|
||||
but you have &const T or &mut T) and also for avoiding the linearity
|
||||
of mut things (when the expected is &mut T and you have &mut T). See
|
||||
|
@ -451,7 +451,7 @@ impl Coerce {
|
|||
let a_unsafe = ty::mk_ptr(self.get_ref().infcx.tcx, mt_a);
|
||||
if_ok!(self.subtype(a_unsafe, b));
|
||||
|
||||
// although borrowed ptrs and unsafe ptrs have the same
|
||||
// although references and unsafe ptrs have the same
|
||||
// representation, we still register an AutoDerefRef so that
|
||||
// regionck knows that the region for `a` must be valid here
|
||||
Ok(Some(@AutoDerefRef(AutoDerefRef {
|
||||
|
|
|
@ -226,11 +226,11 @@ impl ErrorReporting for InferCtxt {
|
|||
infer::Reborrow(span) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
"lifetime of borrowed pointer outlines \
|
||||
"lifetime of reference outlines \
|
||||
lifetime of borrowed content...");
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
"...the borrowed pointer is valid for ",
|
||||
"...the reference is valid for ",
|
||||
sub,
|
||||
"...");
|
||||
note_and_explain_region(
|
||||
|
@ -351,7 +351,7 @@ impl ErrorReporting for InferCtxt {
|
|||
infer::AddrOf(span) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
"borrowed pointer is not valid \
|
||||
"reference is not valid \
|
||||
at the time of borrow");
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
|
@ -362,7 +362,7 @@ impl ErrorReporting for InferCtxt {
|
|||
infer::AutoBorrow(span) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
"automatically borrowed pointer is not valid \
|
||||
"automatically reference is not valid \
|
||||
at the time of borrow");
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
|
@ -532,7 +532,7 @@ impl ErrorReportingHelpers for InferCtxt {
|
|||
infer::Reborrow(span) => {
|
||||
self.tcx.sess.span_note(
|
||||
span,
|
||||
"...so that borrowed pointer does not outlive \
|
||||
"...so that reference does not outlive \
|
||||
borrowed content");
|
||||
}
|
||||
infer::InfStackClosure(span) => {
|
||||
|
@ -586,13 +586,13 @@ impl ErrorReportingHelpers for InferCtxt {
|
|||
infer::AddrOf(span) => {
|
||||
self.tcx.sess.span_note(
|
||||
span,
|
||||
"...so that borrowed pointer is valid \
|
||||
"...so that reference is valid \
|
||||
at the time of borrow");
|
||||
}
|
||||
infer::AutoBorrow(span) => {
|
||||
self.tcx.sess.span_note(
|
||||
span,
|
||||
"...so that automatically borrowed pointer is valid \
|
||||
"...so that automatically reference is valid \
|
||||
at the time of borrow");
|
||||
}
|
||||
infer::BindingTypeIsNotValidAtDecl(span) => {
|
||||
|
|
|
@ -157,7 +157,7 @@ pub enum SubregionOrigin {
|
|||
// Invocation of closure must be within its lifetime
|
||||
InvokeClosure(Span),
|
||||
|
||||
// Dereference of borrowed pointer must be within its lifetime
|
||||
// Dereference of reference must be within its lifetime
|
||||
DerefPointer(Span),
|
||||
|
||||
// Closure bound must not outlive captured free variables
|
||||
|
@ -170,7 +170,7 @@ pub enum SubregionOrigin {
|
|||
// relating `'a` to `'b`
|
||||
RelateObjectBound(Span),
|
||||
|
||||
// Creating a pointer `b` to contents of another borrowed pointer
|
||||
// Creating a pointer `b` to contents of another reference
|
||||
Reborrow(Span),
|
||||
|
||||
// (&'a &'b T) where a >= b
|
||||
|
|
|
@ -226,12 +226,12 @@ corresponds to the *actual execution of the function `add()`*, after
|
|||
all arguments have been evaluated. There is a corresponding lifetime
|
||||
`'b_call` for the execution of `inc()`. If we wanted to be precise
|
||||
about it, the lifetime of the two borrows should be `'a_call` and
|
||||
`'b_call` respectively, since the borrowed pointers that were created
|
||||
`'b_call` respectively, since the references that were created
|
||||
will not be dereferenced except during the execution itself.
|
||||
|
||||
However, this model by itself is not sound. The reason is that
|
||||
while the two borrowed pointers that are created will never be used
|
||||
simultaneously, it is still true that the first borrowed pointer is
|
||||
while the two references that are created will never be used
|
||||
simultaneously, it is still true that the first reference is
|
||||
*created* before the second argument is evaluated, and so even though
|
||||
it will not be *dereferenced* during the evaluation of the second
|
||||
argument, it can still be *invalidated* by that evaluation. Consider
|
||||
|
@ -257,7 +257,7 @@ invalidating the first argument.
|
|||
So, for now, we exclude the `call` lifetimes from our model.
|
||||
Eventually I would like to include them, but we will have to make the
|
||||
borrow checker handle this situation correctly. In particular, if
|
||||
there is a borrowed pointer created whose lifetime does not enclose
|
||||
there is a reference created whose lifetime does not enclose
|
||||
the borrow expression, we must issue sufficient restrictions to ensure
|
||||
that the pointee remains valid.
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use syntax::opt_vec::OptVec;
|
|||
|
||||
/// Defines strategies for handling regions that are omitted. For
|
||||
/// example, if one writes the type `&Foo`, then the lifetime of of
|
||||
/// this borrowed pointer has been omitted. When converting this
|
||||
/// this reference has been omitted. When converting this
|
||||
/// type, the generic functions in astconv will invoke `anon_regions`
|
||||
/// on the provided region-scope to decide how to translate this
|
||||
/// omitted region.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Borrowed pointer utilities
|
||||
//! Utilities for references
|
||||
|
||||
#[cfg(not(test))]
|
||||
use prelude::*;
|
||||
|
|
|
@ -64,7 +64,7 @@ pub unsafe fn transmute<L, G>(thing: L) -> G {
|
|||
#[inline]
|
||||
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }
|
||||
|
||||
/// Coerce a borrowed pointer to have an arbitrary associated region.
|
||||
/// Coerce a reference to have an arbitrary associated region.
|
||||
#[inline]
|
||||
pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T {
|
||||
transmute(ptr)
|
||||
|
@ -82,7 +82,7 @@ pub unsafe fn transmute_immut_unsafe<T,P:RawPtr<T>>(ptr: P) -> *T {
|
|||
transmute(ptr)
|
||||
}
|
||||
|
||||
/// Coerce a borrowed mutable pointer to have an arbitrary associated region.
|
||||
/// Coerce a mutable reference to have an arbitrary associated region.
|
||||
#[inline]
|
||||
pub unsafe fn transmute_mut_region<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
|
||||
transmute(ptr)
|
||||
|
|
|
@ -59,7 +59,7 @@ impl<T> Clone for @T {
|
|||
}
|
||||
|
||||
impl<'a, T> Clone for &'a T {
|
||||
/// Return a shallow copy of the borrowed pointer.
|
||||
/// Return a shallow copy of the reference.
|
||||
#[inline]
|
||||
fn clone(&self) -> &'a T { *self }
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
//! `std` includes modules corresponding to each of the integer types,
|
||||
//! each of the floating point types, the `bool` type, tuples, characters,
|
||||
//! strings (`str`), vectors (`vec`), managed boxes (`managed`), owned
|
||||
//! boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`).
|
||||
//! boxes (`owned`), and unsafe pointers and references (`ptr`, `borrowed`).
|
||||
//! Additionally, `std` provides pervasive types (`option` and `result`),
|
||||
//! task creation and communication primitives (`task`, `comm`), platform
|
||||
//! abstractions (`os` and `path`), basic I/O abstractions (`io`), common
|
||||
|
|
|
@ -71,7 +71,7 @@ traits from other modules. Some notable examples:
|
|||
## Iteration
|
||||
|
||||
The method `iter()` returns an iteration value for a vector or a vector slice.
|
||||
The iterator yields borrowed pointers to the vector's elements, so if the element
|
||||
The iterator yields references to the vector's elements, so if the element
|
||||
type of the vector is `int`, the element type of the iterator is `&int`.
|
||||
|
||||
```rust
|
||||
|
|
|
@ -371,7 +371,7 @@ pub enum Pat_ {
|
|||
PatTup(~[@Pat]),
|
||||
PatBox(@Pat),
|
||||
PatUniq(@Pat),
|
||||
PatRegion(@Pat), // borrowed pointer pattern
|
||||
PatRegion(@Pat), // reference pattern
|
||||
PatLit(@Expr),
|
||||
PatRange(@Expr, @Expr),
|
||||
// [a, b, ..i, y, z] is represented as
|
||||
|
|
|
@ -26,7 +26,7 @@ Supported features (fairly exhaustive):
|
|||
requires an explicit `Eq` bound at the
|
||||
moment. (`TraitDef.additional_bounds`)
|
||||
|
||||
Unsupported: FIXME #6257: calling methods on borrowed pointer fields,
|
||||
Unsupported: FIXME #6257: calling methods on reference fields,
|
||||
e.g. deriving TotalEq/TotalOrd/Clone don't work on `struct A(&int)`,
|
||||
because of how the auto-dereferencing happens.
|
||||
|
||||
|
|
|
@ -8,15 +8,23 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/*! This module contains the Rust parser. It maps source text
|
||||
* to token trees and to ASTs. It contains code for expanding
|
||||
* macros.
|
||||
*/
|
||||
/*!
|
||||
|
||||
The Rust parser and macro expander.
|
||||
|
||||
# Note
|
||||
|
||||
This API is completely unstable and subject to change.
|
||||
|
||||
*/
|
||||
|
||||
#[crate_id = "syntax#0.9"];
|
||||
#[license = "MIT/ASL2"];
|
||||
#[crate_type = "dylib"];
|
||||
#[crate_type = "rlib"];
|
||||
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://static.rust-lang.org/doc/master")];
|
||||
|
||||
#[feature(macro_rules, globs, managed_boxes)];
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ impl<T:Eq + IterBytes + Hash + Freeze + Clone + 'static> Interner<T> {
|
|||
}
|
||||
|
||||
// A StrInterner differs from Interner<String> in that it accepts
|
||||
// borrowed pointers rather than @ ones, resulting in less allocation.
|
||||
// references rather than @ ones, resulting in less allocation.
|
||||
pub struct StrInterner {
|
||||
priv map: @RefCell<HashMap<@str, Name>>,
|
||||
priv vect: @RefCell<~[@str]>,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#[feature(managed_boxes)];
|
||||
|
||||
fn f<T>(x: T) -> @T {
|
||||
@x //~ ERROR value may contain borrowed pointers
|
||||
@x //~ ERROR value may contain references
|
||||
}
|
||||
|
||||
fn g<T:'static>(x: T) -> @T {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Testing that we can't store a borrowed pointer it task-local storage
|
||||
// Testing that we can't store a reference it task-local storage
|
||||
|
||||
use std::local_data;
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ impl<T:Clone> foo for T {
|
|||
}
|
||||
|
||||
fn to_foo<T:Clone>(t: T) {
|
||||
// This version is ok because, although T may contain borrowed
|
||||
// pointers, it never escapes the fn body. We know this because
|
||||
// This version is ok because, although T may contain references
|
||||
// it never escapes the fn body. We know this because
|
||||
// the type of foo includes a region which will be resolved to
|
||||
// the fn body itself.
|
||||
let v = &3;
|
||||
|
@ -34,15 +34,15 @@ fn to_foo<T:Clone>(t: T) {
|
|||
}
|
||||
|
||||
fn to_foo_2<T:Clone>(t: T) -> @foo {
|
||||
// Not OK---T may contain borrowed ptrs and it is going to escape
|
||||
// Not OK---T may contain references and it is going to escape
|
||||
// as part of the returned foo value
|
||||
struct F<T> { f: T }
|
||||
@F {f:t} as @foo //~ ERROR value may contain borrowed pointers; add `'static` bound
|
||||
@F {f:t} as @foo //~ ERROR value may contain references; add `'static` bound
|
||||
}
|
||||
|
||||
fn to_foo_3<T:Clone + 'static>(t: T) -> @foo {
|
||||
// OK---T may escape as part of the returned foo value, but it is
|
||||
// owned and hence does not contain borrowed ptrs
|
||||
// owned and hence does not contain references
|
||||
struct F<T> { f: T }
|
||||
@F {f:t} as @foo
|
||||
}
|
||||
|
|
|
@ -14,9 +14,9 @@ trait foo { fn foo(&self); }
|
|||
|
||||
fn to_foo<T:Clone + foo>(t: T) -> @foo {
|
||||
@t as @foo
|
||||
//~^ ERROR value may contain borrowed pointers; add `'static` bound
|
||||
//~^ ERROR value may contain references; add `'static` bound
|
||||
//~^^ ERROR cannot pack type
|
||||
//~^^^ ERROR value may contain borrowed pointers
|
||||
//~^^^ ERROR value may contain references
|
||||
}
|
||||
|
||||
fn to_foo2<T:Clone + foo + 'static>(t: T) -> @foo {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
// xfail-test #5723
|
||||
|
||||
// Test that you cannot escape a borrowed pointer
|
||||
// Test that you cannot escape a reference
|
||||
// into a trait.
|
||||
|
||||
struct ctxt { v: uint }
|
||||
|
@ -29,7 +29,7 @@ fn make_gc() -> @get_ctxt {
|
|||
let ctxt = ctxt { v: 22u };
|
||||
let hc = has_ctxt { c: &ctxt };
|
||||
return @hc as @get_ctxt;
|
||||
//^~ ERROR source contains borrowed pointer
|
||||
//^~ ERROR source contains reference
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -175,10 +175,10 @@ fn main() {
|
|||
// managed box
|
||||
let @aa = @(34, 35);
|
||||
|
||||
// borrowed pointer
|
||||
// reference
|
||||
let &bb = &(36, 37);
|
||||
|
||||
// contained borrowed pointer
|
||||
// contained reference
|
||||
let (&cc, _) = (&38, 39);
|
||||
|
||||
// unique pointer
|
||||
|
|
|
@ -51,7 +51,7 @@ struct AsciiArt {
|
|||
priv lines: ~[~[char]],
|
||||
|
||||
// This struct can be quite large so we'll disable copying: developers need
|
||||
// to either pass these structs around via borrowed pointers or move them.
|
||||
// to either pass these structs around via references or move them.
|
||||
}
|
||||
|
||||
impl Drop for AsciiArt {
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
// except according to those terms.
|
||||
|
||||
/*
|
||||
# ICE when returning struct with borrowed pointer to trait
|
||||
# ICE when returning struct with reference to trait
|
||||
|
||||
A function which takes a borrowed pointer to a trait and returns a
|
||||
struct with that borrowed pointer results in an ICE.
|
||||
A function which takes a reference to a trait and returns a
|
||||
struct with that reference results in an ICE.
|
||||
|
||||
This does not occur with concrete types, only with borrowed pointers
|
||||
This does not occur with concrete types, only with references
|
||||
to traits.
|
||||
*/
|
||||
|
||||
|
|
Loading…
Reference in New Issue