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_BUILD_DIR
|
||||||
export CFG_VERSION
|
export CFG_VERSION
|
||||||
export CFG_VERSION_WIN
|
export CFG_VERSION_WIN
|
||||||
|
export CFG_RELEASE
|
||||||
export CFG_BUILD
|
export CFG_BUILD
|
||||||
export CFG_LLVM_ROOT
|
export CFG_LLVM_ROOT
|
||||||
export CFG_ENABLE_MINGW_CROSS
|
export CFG_ENABLE_MINGW_CROSS
|
||||||
|
|
|
@ -806,6 +806,7 @@ do
|
||||||
make_dir $h/test/doc-guide-container
|
make_dir $h/test/doc-guide-container
|
||||||
make_dir $h/test/doc-guide-tasks
|
make_dir $h/test/doc-guide-tasks
|
||||||
make_dir $h/test/doc-guide-conditions
|
make_dir $h/test/doc-guide-conditions
|
||||||
|
make_dir $h/test/doc-complement-cheatsheet
|
||||||
make_dir $h/test/doc-rust
|
make_dir $h/test/doc-rust
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
|
@ -6,41 +6,41 @@
|
||||||
|
|
||||||
Use [`ToStr`](http://static.rust-lang.org/doc/master/std/to_str/trait.ToStr.html).
|
Use [`ToStr`](http://static.rust-lang.org/doc/master/std/to_str/trait.ToStr.html).
|
||||||
|
|
||||||
```rust
|
~~~
|
||||||
let x: int = 42;
|
let x: int = 42;
|
||||||
let y: ~str = x.to_str();
|
let y: ~str = x.to_str();
|
||||||
```
|
~~~
|
||||||
|
|
||||||
**String to int**
|
**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).
|
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 x: Option<int> = from_str("42");
|
||||||
let y: int = x.unwrap();
|
let y: int = x.unwrap();
|
||||||
```
|
~~~
|
||||||
|
|
||||||
**Int to string, in non-base-10**
|
**Int to string, in non-base-10**
|
||||||
|
|
||||||
Use [`ToStrRadix`](http://static.rust-lang.org/doc/master/std/num/trait.ToStrRadix.html).
|
Use [`ToStrRadix`](http://static.rust-lang.org/doc/master/std/num/trait.ToStrRadix.html).
|
||||||
|
|
||||||
```rust
|
~~~
|
||||||
use std::num::ToStrRadix;
|
use std::num::ToStrRadix;
|
||||||
|
|
||||||
let x: int = 42;
|
let x: int = 42;
|
||||||
let y: ~str = x.to_str_radix(16);
|
let y: ~str = x.to_str_radix(16);
|
||||||
```
|
~~~
|
||||||
|
|
||||||
**String to int, in non-base-10**
|
**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).
|
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;
|
use std::num::from_str_radix;
|
||||||
|
|
||||||
let x: Option<int> = from_str_radix("deadbeef", 16);
|
let x: Option<i64> = from_str_radix("deadbeef", 16);
|
||||||
let y: int = x.unwrap();
|
let y: i64 = x.unwrap();
|
||||||
```
|
~~~
|
||||||
|
|
||||||
# File operations
|
# 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.
|
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::path::Path;
|
||||||
use std::io::fs::File;
|
use std::io::fs::File;
|
||||||
|
|
||||||
let path : Path = Path::new("Doc-FAQ-Cheatsheet.md");
|
let path : Path = Path::new("Doc-FAQ-Cheatsheet.md");
|
||||||
let on_error = || fail!("open of {:?} failed", path);
|
let on_error = || fail!("open of {:?} failed", path);
|
||||||
let reader : File = File::open(&path).unwrap_or_else(on_error);
|
let reader : File = File::open(&path).unwrap_or_else(on_error);
|
||||||
```
|
~~~
|
||||||
|
|
||||||
## How do I iterate over the lines in a file?
|
## 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).
|
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::buffered::BufferedReader;
|
||||||
|
# use std::io::mem::MemReader;
|
||||||
|
|
||||||
|
# let reader = MemReader::new(~[]);
|
||||||
|
|
||||||
let mut reader = BufferedReader::new(reader);
|
let mut reader = BufferedReader::new(reader);
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
print!("line: {}", line);
|
print!("line: {}", line);
|
||||||
}
|
}
|
||||||
```
|
~~~
|
||||||
|
|
||||||
# String operations
|
# 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.
|
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 str = "Hello, this is some random string";
|
||||||
let index: Option<uint> = str.find_str("rand");
|
let index: Option<uint> = str.find_str("rand");
|
||||||
```
|
~~~
|
||||||
|
|
||||||
# Containers
|
# 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.
|
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 u: ~[u32] = ~[0, 1, 2];
|
||||||
let v: &[u32] = &[0, 1, 2, 3];
|
let v: &[u32] = &[0, 1, 2, 3];
|
||||||
let w: [u32, .. 5] = [0, 1, 2, 3, 4];
|
let w: [u32, .. 5] = [0, 1, 2, 3, 4];
|
||||||
|
|
||||||
println!("u: {}, v: {}, w: {}", u.len(), v.len(), w.len()); // 3, 4, 5
|
println!("u: {}, v: {}, w: {}", u.len(), v.len(), w.len()); // 3, 4, 5
|
||||||
```
|
~~~
|
||||||
|
|
||||||
## How do I iterate over a vector?
|
## 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.
|
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];
|
let values: ~[int] = ~[1, 2, 3, 4, 5];
|
||||||
for value in values.iter() { // value: &int
|
for value in values.iter() { // value: &int
|
||||||
println!("{}", *value);
|
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.)
|
(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?
|
## How do I store a function in a struct?
|
||||||
|
|
||||||
```rust
|
~~~
|
||||||
struct Foo {
|
struct Foo {
|
||||||
myfunc: fn(int, uint) -> i32
|
myfunc: fn(int, uint) -> i32
|
||||||
}
|
}
|
||||||
|
@ -131,7 +134,7 @@ fn main() {
|
||||||
println!("{}", (f.myfunc)(1, 2));
|
println!("{}", (f.myfunc)(1, 2));
|
||||||
println!("{}", (g.myfunc)(3, 4));
|
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.
|
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:
|
[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 Open {}
|
||||||
enum Closed {}
|
enum Closed {}
|
||||||
```
|
~~~
|
||||||
|
|
||||||
Phantom types are useful for enforcing state at compile time. For example:
|
Phantom types are useful for enforcing state at compile time. For example:
|
||||||
|
|
||||||
```rust
|
~~~
|
||||||
struct Door<State>(~str);
|
struct Door<State>(~str);
|
||||||
|
|
||||||
|
struct Open;
|
||||||
|
struct Closed;
|
||||||
|
|
||||||
fn close(Door(name): Door<Open>) -> Door<Closed> {
|
fn close(Door(name): Door<Open>) -> Door<Closed> {
|
||||||
Door::<Closed>(name)
|
Door::<Closed>(name)
|
||||||
}
|
}
|
||||||
|
@ -157,20 +163,25 @@ fn open(Door(name): Door<Closed>) -> Door<Open> {
|
||||||
Door::<Open>(name)
|
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>`
|
let _ = close(Door::<Closed>(~"front")); // error: mismatched types: expected `main::Door<main::Open>` but found `main::Door<main::Closed>`
|
||||||
```
|
~~~
|
||||||
|
|
||||||
# FFI (Foreign Function Interface)
|
# FFI (Foreign Function Interface)
|
||||||
|
|
||||||
## C function signature conversions
|
## C function signature conversions
|
||||||
|
|
||||||
Description | C signature | Equivalent Rust signature
|
Description C signature Equivalent Rust signature
|
||||||
----------------------|----------------------------------------------|------------------------------------------
|
---------------------- ---------------------------------------------- ------------------------------------------
|
||||||
no parameters | `void foo(void);` | `fn foo();`
|
no parameters `void foo(void);` `fn foo();`
|
||||||
return value | `int foo(void);` | `fn foo() -> c_int;`
|
return value `int foo(void);` `fn foo() -> c_int;`
|
||||||
function parameters | `void foo(int x, int y);` | `fn foo(x: int, y: 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);`
|
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.
|
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:
|
You might see things like this in C APIs:
|
||||||
|
|
||||||
```c
|
~~~ {.notrust}
|
||||||
typedef struct Window Window;
|
typedef struct Window Window;
|
||||||
Window* createWindow(int width, int height);
|
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:
|
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 {}
|
enum Window {}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn createWindow(width: c_int, height: c_int) -> *Window;
|
fn createWindow(width: c_int, height: c_int) -> *Window;
|
||||||
}
|
}
|
||||||
```
|
~~~
|
||||||
|
|
||||||
Using a phantom type ensures that the handles cannot be (safely) constructed in client code.
|
Using a phantom type ensures that the handles cannot be (safely) constructed in client code.
|
||||||
|
|
||||||
|
@ -200,4 +211,4 @@ For small examples, have full type annotations, as much as is reasonable, to kee
|
||||||
|
|
||||||
Similar documents for other programming languages:
|
Similar documents for other programming languages:
|
||||||
|
|
||||||
* [http://pleac.sourceforge.net/](http://pleac.sourceforge.net)
|
* [http://pleac.sourceforge.net/](http://pleac.sourceforge.net)
|
||||||
|
|
|
@ -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
|
* Managed boxes may not be shared between tasks
|
||||||
* Owned boxes may be transferred (moved) 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
|
* References 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
|
* References can only be formed when it will provably be outlived by the referent
|
||||||
* Borrowed pointers to managed box pointers keep the managed boxes alive
|
* References to managed box pointers keep the managed boxes alive
|
||||||
* Borrowed pointers to owned boxes prevent their ownership from being transferred
|
* References to owned boxes prevent their ownership from being transferred
|
||||||
* Borrowed pointers employ region-based alias analysis to ensure correctness
|
* References employ region-based alias analysis to ensure correctness
|
||||||
|
|
||||||
## Why aren't function signatures inferred? Why only local slots?
|
## 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
|
# Introduction
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
% Containers and Iterators Guide
|
% The Rust Containers and Iterators Guide
|
||||||
|
|
||||||
# Containers
|
# Containers
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
% Rust Foreign Function Interface Guide
|
% The Rust Foreign Function Interface Guide
|
||||||
|
|
||||||
# Introduction
|
# 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
|
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
|
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
|
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
|
prefer using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions
|
||||||
about them.
|
about them.
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
% Rust Borrowed Pointers Guide
|
% The Rust References and Lifetimes Guide
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
Borrowed pointers are one of the more flexible and powerful tools available in
|
References are one of the more flexible and powerful tools available in
|
||||||
Rust. A borrowed pointer can point anywhere: into the managed or exchange
|
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
|
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
|
unlike C and C++ compilers, the Rust compiler includes special static checks
|
||||||
that ensure that programs use borrowed pointers safely. Another advantage of
|
that ensure that programs use references safely. Another advantage of
|
||||||
borrowed pointers is that they are invisible to the garbage collector, so
|
references is that they are invisible to the garbage collector, so
|
||||||
working with borrowed pointers helps reduce the overhead of automatic memory
|
working with references helps reduce the overhead of automatic memory
|
||||||
management.
|
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
|
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.
|
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
|
underpinnings (region pointers), the core concepts will be familiar to
|
||||||
anyone who has worked with C or C++. Therefore, the best way to explain
|
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
|
how they are used—and their limitations—is probably just to work
|
||||||
|
@ -24,8 +24,8 @@ through several examples.
|
||||||
|
|
||||||
# By example
|
# By example
|
||||||
|
|
||||||
Borrowed pointers are called *borrowed* because they are only valid for
|
References, sometimes known as *borrowed pointers*, are only valid for
|
||||||
a limited duration. Borrowed pointers never claim any kind of ownership
|
a limited duration. References never claim any kind of ownership
|
||||||
over the data that they point to: instead, they are used for cases
|
over the data that they point to: instead, they are used for cases
|
||||||
where you would like to use data for a short time.
|
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
|
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
|
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
|
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:
|
this:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
@ -89,7 +89,7 @@ name for the same data.
|
||||||
|
|
||||||
In contrast, we can pass the boxes `managed_box` and `owned_box` to
|
In contrast, we can pass the boxes `managed_box` and `owned_box` to
|
||||||
`compute_distance` directly. The compiler automatically converts a box like
|
`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
|
of borrowing: in this case, the caller lends the contents of the managed or
|
||||||
owned box to the callee.
|
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
|
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
|
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
|
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.
|
before you can make full use of it again.
|
||||||
|
|
||||||
# Other uses for the & operator
|
# 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
|
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
|
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`:
|
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
|
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
|
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
|
is simply a pointer, nothing more. Therefore, avoiding C's problems
|
||||||
with dangling pointers requires a compile-time safety check.
|
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
|
error. We'll be discussing lifetimes more in the examples to come, and
|
||||||
a more thorough introduction is also available.
|
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
|
ensure that the pointer remains valid for its entire
|
||||||
lifetime. Sometimes this is relatively easy, such as when taking the
|
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:
|
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
|
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
|
work to prove that code will not free `x.f`. This is true even if the
|
||||||
code mutates `x`.
|
code mutates `x`.
|
||||||
|
@ -384,7 +384,7 @@ enum Shape {
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Now we might write a function to compute the area of a shape. This
|
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.
|
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
|
box: it must be able to guarantee that the `enum` will not be
|
||||||
overwritten for the duration of the borrow. In fact, the compiler
|
overwritten for the duration of the borrow. In fact, the compiler
|
||||||
would accept the example we gave earlier. The example is safe because
|
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
|
immutable memory containing a `shape`". If, however, the type of that
|
||||||
pointer were `&mut Shape`, then the ref binding would be ill-typed.
|
pointer were `&mut Shape`, then the ref binding would be ill-typed.
|
||||||
Just as with owned boxes, the compiler will permit `ref` bindings
|
Just as with owned boxes, the compiler will permit `ref` bindings
|
||||||
into data owned by the stack frame even if the data are mutable,
|
into data owned by the stack frame even if the data are mutable,
|
||||||
but otherwise it requires that the data reside in immutable memory.
|
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
|
“downward” direction. That is, a method or code block creates a
|
||||||
borrowed pointer, then uses it within the same scope. It is also
|
reference, then uses it within the same scope. It is also
|
||||||
possible to return borrowed pointers as the result of a function, but
|
possible to return references as the result of a function, but
|
||||||
as we'll see, doing so requires some explicit annotation.
|
as we'll see, doing so requires some explicit annotation.
|
||||||
|
|
||||||
For example, we could write a subroutine like this:
|
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
|
pointer with lifetime `r` and returns a pointer with that same
|
||||||
lifetime.
|
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
|
are derived from a parameter to the procedure. In that case, the
|
||||||
pointer result will always have the same lifetime as one of the
|
pointer result will always have the same lifetime as one of the
|
||||||
parameters; named lifetimes indicate which parameter that
|
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
|
Here, the function `get_x_sh()` takes a managed box as input and
|
||||||
returns a borrowed pointer. As before, the lifetime of the borrowed
|
returns a reference. As before, the lifetime of the reference
|
||||||
pointer that will be returned is a parameter (specified by the
|
that will be returned is a parameter (specified by the
|
||||||
caller). That means that `get_x_sh()` promises to return a borrowed
|
caller). That means that `get_x_sh()` promises to return a reference
|
||||||
pointer that is valid for as long as the caller would like: this is
|
that is valid for as long as the caller would like: this is
|
||||||
subtly different from the first example, which promised to return a
|
subtly different from the first example, which promised to return a
|
||||||
pointer that was valid for as long as its pointer argument was valid.
|
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.
|
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
|
In general, if you borrow a managed (or owned) box to create a
|
||||||
borrowed pointer, the pointer will only be valid within the function
|
reference, it will only be valid within the function
|
||||||
and cannot be returned. This is why the typical way to return borrowed
|
and cannot be returned. This is why the typical way to return references
|
||||||
pointers is to take borrowed pointers as input (the only other case in
|
is to take references as input (the only other case in
|
||||||
which it can be legal to return a borrowed pointer is if the pointer
|
which it can be legal to return a reference is if it
|
||||||
points at a static constant).
|
points at a static constant).
|
||||||
|
|
||||||
# Named lifetimes
|
# 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`. In practice, this means that, in the caller, the
|
||||||
lifetime `r` will be the *intersection of the lifetime of the three
|
lifetime `r` will be the *intersection of the lifetime of the three
|
||||||
region parameters*. This may be overly conservative, as in this
|
region parameters*. This may be overly conservative, as in this
|
||||||
|
@ -657,7 +657,7 @@ This is equivalent to the previous definition.
|
||||||
|
|
||||||
# Conclusion
|
# 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
|
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.
|
and give more examples.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
% Rust Macros Guide
|
% The Rust Macros Guide
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
Rust's pointers are one of its more unique and compelling features. 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
|
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
|
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
|
# 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
|
to accidentally stab yourself. Therefore, Rust is made in a way such that you
|
||||||
don't need them very often.
|
don't need them very often.
|
||||||
|
|
||||||
"But tutorial!" you may cry. "My co-worker wrote a function that looks like
|
"But guide!" you may cry. "My co-worker wrote a function that looks like this:
|
||||||
this:
|
|
||||||
|
|
||||||
~~~rust
|
~~~rust
|
||||||
fn succ(x: &int) -> int { *x + 1 }
|
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:
|
So I wrote this code to try it out:
|
||||||
|
|
||||||
~~~rust {.xfail-test}
|
~~~rust{.xfail-test}
|
||||||
fn main() {
|
fn main() {
|
||||||
let number = 5;
|
let number = 5;
|
||||||
let succ_number = succ(number);
|
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
|
Here are the use-cases for pointers. I've prefixed them with the name of the
|
||||||
pointer that satisfies that use-case:
|
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.
|
object, so indirection is mandatory.
|
||||||
2. Owned: You need a recursive data structure. These can be infinite sized, so
|
2. Owned: You need a recursive data structure. These can be infinite sized, so
|
||||||
indirection is mandatory.
|
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
|
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
|
complicated. Using a managed pointer will activate Rust's garbage collection
|
||||||
mechanism.
|
mechanism.
|
||||||
5: Borrowed: You're writing a function, and you need a pointer, but you don't
|
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 borrowed pointer, callers
|
care about its ownership. If you make the argument a reference, callers
|
||||||
can send in whatever kind they want.
|
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
|
of pointers in Rust: use them for a deliberate purpose, not just to make the
|
||||||
compiler happy.
|
compiler happy.
|
||||||
|
|
||||||
## A note for those proficient in pointers
|
## 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
|
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
|
like Java, you can't even have objects without a pointer to them. Therefore, if
|
||||||
you were writing this Rust code:
|
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
|
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.'
|
'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
|
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
|
## 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
|
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.
|
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)))
|
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,
|
elements are in the list. Without knowing the length, we don't know the size,
|
||||||
and therefore require the indirection that pointers offer.
|
and therefore require the indirection that pointers offer.
|
||||||
|
|
||||||
|
@ -250,13 +249,19 @@ struct.
|
||||||
|
|
||||||
# Managed Pointers
|
# 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
|
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
|
some data isn't convenient or possible. This generally happens when your
|
||||||
program is very large and complicated.
|
program is very large and complicated.
|
||||||
|
|
||||||
For example, let's say you're using an owned pointer, and you want to do this:
|
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 {
|
struct Point {
|
||||||
x: int,
|
x: int,
|
||||||
y: int,
|
y: int,
|
||||||
|
@ -310,14 +315,14 @@ managed pointers:
|
||||||
1. They activate Rust's garbage collector. Other pointer types don't share this
|
1. They activate Rust's garbage collector. Other pointer types don't share this
|
||||||
drawback.
|
drawback.
|
||||||
2. You cannot pass this data to another task. Shared ownership across
|
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.
|
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:
|
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
|
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
|
sense, they're simple: just keep whatever ownership the data already has. For
|
||||||
example:
|
example:
|
||||||
|
@ -346,13 +351,13 @@ fn main() {
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
This prints `5.83095189`. You can see that the `compute_distance` function
|
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,
|
course, if this were a real program, we wouldn't have any of these pointers,
|
||||||
they're just there to demonstrate the concepts.
|
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
|
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
|
an ordinary pointer in a C program. They introduce zero overhead. The compiler
|
||||||
does all safety checks at compile time.
|
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
|
'lifetimes'. Here's the simple explanation: would you expect this code to
|
||||||
compile?
|
compile?
|
||||||
|
|
||||||
~~~rust {.xfail-test}
|
~~~rust{.xfail-test}
|
||||||
fn main() {
|
fn main() {
|
||||||
println(x.to_str());
|
println(x.to_str());
|
||||||
let x = 5;
|
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
|
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
|
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:
|
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
|
~~~rust
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut x = ~5;
|
let mut x = ~5;
|
||||||
if(*x < 10) {
|
if *x < 10 {
|
||||||
let y = &x;
|
let y = &x;
|
||||||
println!("Oh no: {:?}", y);
|
println!("Oh no: {:?}", y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*x = *x - 1;
|
*x -= 1;
|
||||||
println!("Oh no: {:?}", x);
|
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
|
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:
|
mutated, and therefore, lets us pass. This wouldn't work:
|
||||||
|
|
||||||
~~~rust {.xfail-test}
|
~~~rust{.xfail-test}
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut x = ~5;
|
let mut x = ~5;
|
||||||
if(*x < 10) {
|
if *x < 10 {
|
||||||
let y = &x;
|
let y = &x;
|
||||||
*x = *x - 1;
|
*x -= 1;
|
||||||
|
|
||||||
println!("Oh no: {:?}", y);
|
println!("Oh no: {:?}", y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*x = *x - 1;
|
*x -= 1;
|
||||||
println!("Oh no: {:?}", x);
|
println!("Oh no: {:?}", x);
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
@ -408,7 +413,7 @@ It gives this error:
|
||||||
|
|
||||||
~~~ {.notrust}
|
~~~ {.notrust}
|
||||||
test.rs:5:8: 5:10 error: cannot assign to `*x` because it is borrowed
|
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:16: 4:18 note: borrow of `*x` occurs here
|
||||||
test.rs:4 let y = &x;
|
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
|
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
|
hard for a computer, too! There is an entire [guide devoted to references
|
||||||
pointers and lifetimes](tutorial-lifetimes.html) that goes into lifetimes in
|
and lifetimes](guide-lifetimes.html) that goes into lifetimes in
|
||||||
great detail, so if you want the full details, check that out.
|
great detail, so if you want the full details, check that out.
|
||||||
|
|
||||||
# Returning Pointers
|
# 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
|
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.
|
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
|
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
|
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
|
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
|
`@int`, passes a pointer to that memory into `foo` as `x`, and then `foo` writes
|
||||||
new box. This writes the return value directly into the allocated box.
|
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
|
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
|
returning values from your code. Allow the caller to choose how they want to
|
||||||
|
@ -479,4 +485,4 @@ use your output.
|
||||||
|
|
||||||
# Related Resources
|
# Related Resources
|
||||||
|
|
||||||
* [Lifetimes tutorial](tutorial-lifetimes.html)
|
* [Lifetimes guide](guide-lifetimes.html)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
% Rust Packaging Guide
|
% The Rust Packaging Guide
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
% Rust Tasks and Communication Guide
|
% The Rust Tasks and Communication Guide
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
% Rust Testing Guide
|
% The Rust Testing Guide
|
||||||
|
|
||||||
# Quick start
|
# Quick start
|
||||||
|
|
||||||
To create test functions, add a `#[test]` attribute like this:
|
To create test functions, add a `#[test]` attribute like this:
|
||||||
|
|
||||||
```rust
|
~~~
|
||||||
fn return_two() -> int {
|
fn return_two() -> int {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
@ -14,17 +14,17 @@ fn return_two_test() {
|
||||||
let x = return_two();
|
let x = return_two();
|
||||||
assert!(x == 2);
|
assert!(x == 2);
|
||||||
}
|
}
|
||||||
```
|
~~~
|
||||||
|
|
||||||
To run these tests, use `rustc --test`:
|
To run these tests, use `rustc --test`:
|
||||||
|
|
||||||
```
|
~~~ {.notrust}
|
||||||
$ rustc --test foo.rs; ./foo
|
$ rustc --test foo.rs; ./foo
|
||||||
running 1 test
|
running 1 test
|
||||||
test return_two_test ... ok
|
test return_two_test ... ok
|
||||||
|
|
||||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
|
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
|
||||||
```
|
~~~
|
||||||
|
|
||||||
`rustc foo.rs` will *not* compile the tests, since `#[test]` implies
|
`rustc foo.rs` will *not* compile the tests, since `#[test]` implies
|
||||||
`#[cfg(test)]`. The `--test` flag to `rustc` implies `--cfg test`.
|
`#[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
|
Rust has built in support for simple unit testing. Functions can be
|
||||||
marked as unit tests using the 'test' attribute.
|
marked as unit tests using the 'test' attribute.
|
||||||
|
|
||||||
```rust
|
~~~
|
||||||
#[test]
|
#[test]
|
||||||
fn return_none_if_empty() {
|
fn return_none_if_empty() {
|
||||||
// ... test code ...
|
// ... test code ...
|
||||||
}
|
}
|
||||||
```
|
~~~
|
||||||
|
|
||||||
A test function's signature must have no arguments and no return
|
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
|
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
|
When compiling a crate with the '--test' flag '--cfg test' is also
|
||||||
implied, so that tests can be conditionally compiled.
|
implied, so that tests can be conditionally compiled.
|
||||||
|
|
||||||
```rust
|
~~~
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -62,7 +62,7 @@ mod tests {
|
||||||
// ... test code ...
|
// ... test code ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
~~~
|
||||||
|
|
||||||
Additionally #[test] items behave as if they also have the
|
Additionally #[test] items behave as if they also have the
|
||||||
#[cfg(test)] attribute, and will not be compiled when the --test flag
|
#[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
|
task to fail then the test will be counted as successful; otherwise it
|
||||||
will be counted as a failure. For example:
|
will be counted as a failure. For example:
|
||||||
|
|
||||||
```rust
|
~~~
|
||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn test_out_of_bounds_failure() {
|
fn test_out_of_bounds_failure() {
|
||||||
let v: [int] = [];
|
let v: [int] = [];
|
||||||
v[0];
|
v[0];
|
||||||
}
|
}
|
||||||
```
|
~~~
|
||||||
|
|
||||||
A test runner built with the '--test' flag supports a limited set of
|
A test runner built with the '--test' flag supports a limited set of
|
||||||
arguments to control which tests are run: the first free argument
|
arguments to control which tests are run: the first free argument
|
||||||
|
@ -126,7 +126,7 @@ amount.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```rust
|
~~~
|
||||||
extern mod extra;
|
extern mod extra;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ fn initialise_a_vector(b: &mut extra::test::BenchHarness) {
|
||||||
b.iter(|| {vec::from_elem(1024, 0u64);} );
|
b.iter(|| {vec::from_elem(1024, 0u64);} );
|
||||||
b.bytes = 1024 * 8;
|
b.bytes = 1024 * 8;
|
||||||
}
|
}
|
||||||
```
|
~~~
|
||||||
|
|
||||||
The benchmark runner will calibrate measurement of the benchmark
|
The benchmark runner will calibrate measurement of the benchmark
|
||||||
function to run the `iter` block "enough" times to get a reliable
|
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
|
### Typical test run
|
||||||
|
|
||||||
```
|
~~~ {.notrust}
|
||||||
> mytests
|
> mytests
|
||||||
|
|
||||||
running 30 tests
|
running 30 tests
|
||||||
|
@ -178,11 +178,11 @@ running driver::tests::mytest2 ... ignored
|
||||||
running driver::tests::mytest30 ... ok
|
running driver::tests::mytest30 ... ok
|
||||||
|
|
||||||
result: ok. 28 passed; 0 failed; 2 ignored
|
result: ok. 28 passed; 0 failed; 2 ignored
|
||||||
```
|
~~~ {.notrust}
|
||||||
|
|
||||||
### Test run with failures
|
### Test run with failures
|
||||||
|
|
||||||
```
|
~~~ {.notrust}
|
||||||
> mytests
|
> mytests
|
||||||
|
|
||||||
running 30 tests
|
running 30 tests
|
||||||
|
@ -192,11 +192,11 @@ running driver::tests::mytest2 ... ignored
|
||||||
running driver::tests::mytest30 ... FAILED
|
running driver::tests::mytest30 ... FAILED
|
||||||
|
|
||||||
result: FAILED. 27 passed; 1 failed; 2 ignored
|
result: FAILED. 27 passed; 1 failed; 2 ignored
|
||||||
```
|
~~~
|
||||||
|
|
||||||
### Running ignored tests
|
### Running ignored tests
|
||||||
|
|
||||||
```
|
~~~ {.notrust}
|
||||||
> mytests --ignored
|
> mytests --ignored
|
||||||
|
|
||||||
running 2 tests
|
running 2 tests
|
||||||
|
@ -204,11 +204,11 @@ running driver::tests::mytest2 ... failed
|
||||||
running driver::tests::mytest10 ... ok
|
running driver::tests::mytest10 ... ok
|
||||||
|
|
||||||
result: FAILED. 1 passed; 1 failed; 0 ignored
|
result: FAILED. 1 passed; 1 failed; 0 ignored
|
||||||
```
|
~~~
|
||||||
|
|
||||||
### Running a subset of tests
|
### Running a subset of tests
|
||||||
|
|
||||||
```
|
~~~ {.notrust}
|
||||||
> mytests mytest1
|
> mytests mytest1
|
||||||
|
|
||||||
running 11 tests
|
running 11 tests
|
||||||
|
@ -218,11 +218,11 @@ running driver::tests::mytest10 ... ignored
|
||||||
running driver::tests::mytest19 ... ok
|
running driver::tests::mytest19 ... ok
|
||||||
|
|
||||||
result: ok. 11 passed; 0 failed; 1 ignored
|
result: ok. 11 passed; 0 failed; 1 ignored
|
||||||
```
|
~~~
|
||||||
|
|
||||||
### Running benchmarks
|
### Running benchmarks
|
||||||
|
|
||||||
```
|
~~~ {.notrust}
|
||||||
> mytests --bench
|
> mytests --bench
|
||||||
|
|
||||||
running 2 tests
|
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 initialise_a_vector ... bench: 424 ns/iter (+/- 99) = 19320 MB/s
|
||||||
|
|
||||||
test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured
|
test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured
|
||||||
```
|
~~~
|
||||||
|
|
||||||
## Saving and ratcheting metrics
|
## Saving and ratcheting metrics
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
# Guides
|
# Guides
|
||||||
|
|
||||||
[Pointers](guide-pointers.html)
|
[Pointers](guide-pointers.html)
|
||||||
[Lifetimes](guide-lifetimes.html)
|
[References and Lifetimes](guide-lifetimes.html)
|
||||||
[Containers and Iterators](guide-container.html)
|
[Containers and Iterators](guide-container.html)
|
||||||
[Tasks and Communication](guide-tasks.html)
|
[Tasks and Communication](guide-tasks.html)
|
||||||
[Foreign Function Interface](guide-ffi.html)
|
[Foreign Function Interface](guide-ffi.html)
|
||||||
|
@ -24,7 +24,11 @@
|
||||||
# Libraries
|
# Libraries
|
||||||
|
|
||||||
[std](std/index.html)
|
[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
|
# Tooling
|
||||||
|
|
||||||
|
|
44
doc/rust.md
44
doc/rust.md
|
@ -1,4 +1,4 @@
|
||||||
% Rust Reference Manual
|
% The Rust Reference Manual
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
|
@ -1215,7 +1215,7 @@ A static item must have a _constant expression_ giving its definition.
|
||||||
|
|
||||||
Static items must be explicitly typed.
|
Static items must be explicitly typed.
|
||||||
The type may be ```bool```, ```char```, a number, or a type derived from those primitive types.
|
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.
|
fixed-size arrays, tuples, and structs.
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
|
@ -1841,7 +1841,7 @@ A complete list of the built-in language items follows:
|
||||||
`owned`
|
`owned`
|
||||||
: Are uniquely owned.
|
: Are uniquely owned.
|
||||||
`durable`
|
`durable`
|
||||||
: Contain borrowed pointers.
|
: Contain references.
|
||||||
`drop`
|
`drop`
|
||||||
: Have finalizers.
|
: Have finalizers.
|
||||||
`add`
|
`add`
|
||||||
|
@ -1898,11 +1898,11 @@ A complete list of the built-in language items follows:
|
||||||
`free`
|
`free`
|
||||||
: Free memory that was allocated on the managed heap.
|
: Free memory that was allocated on the managed heap.
|
||||||
`borrow_as_imm`
|
`borrow_as_imm`
|
||||||
: Create an immutable borrowed pointer to a mutable value.
|
: Create an immutable reference to a mutable value.
|
||||||
`return_to_mut`
|
`return_to_mut`
|
||||||
: Release a borrowed pointer created with `return_to_mut`
|
: Release a reference created with `return_to_mut`
|
||||||
`check_not_borrowed`
|
`check_not_borrowed`
|
||||||
: Fail if a value has existing borrowed pointers to it.
|
: Fail if a value has existing references to it.
|
||||||
`strdup_uniq`
|
`strdup_uniq`
|
||||||
: Return a new unique string
|
: Return a new unique string
|
||||||
containing a copy of the contents of a 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 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.
|
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
|
#### 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,
|
: [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.
|
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.
|
: Borrow operator. Returns a reference, pointing to its operand.
|
||||||
The operand of a borrowed pointer is statically proven to outlive the resulting pointer.
|
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.
|
If the borrow-checker cannot prove this, it is a compilation error.
|
||||||
|
|
||||||
### Binary operator expressions
|
### Binary operator expressions
|
||||||
|
@ -2894,9 +2894,9 @@ match x {
|
||||||
Patterns that bind variables
|
Patterns that bind variables
|
||||||
default to binding to a copy or move of the matched value
|
default to binding to a copy or move of the matched value
|
||||||
(depending on the matched value's type).
|
(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,
|
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,
|
A pattern that's just an identifier,
|
||||||
like `Nil` in the previous answer,
|
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.
|
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.
|
Releasing an owning pointer immediately releases its corresponding owned box.
|
||||||
|
|
||||||
Borrowed pointers (`&`)
|
References (`&`)
|
||||||
: These point to memory _owned by some other value_.
|
: 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,
|
or by applying the borrowing operator `&` to some other value,
|
||||||
including [lvalues, rvalues or temporaries](#lvalues-rvalues-and-temporaries).
|
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`,
|
References are written `&content`, or in some cases `&'f content` for some lifetime-variable `f`,
|
||||||
for example `&int` means a borrowed pointer to an integer.
|
for example `&int` means a reference to an integer.
|
||||||
Copying a borrowed pointer is a "shallow" operation:
|
Copying a reference is a "shallow" operation:
|
||||||
it involves only copying the pointer itself.
|
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,
|
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 (`*`)
|
||||||
: Raw pointers are pointers without safety or liveness guarantees.
|
: Raw pointers are pointers without safety or liveness guarantees.
|
||||||
|
@ -3338,7 +3338,7 @@ The kinds are:
|
||||||
This kind includes scalars and immutable references,
|
This kind includes scalars and immutable references,
|
||||||
as well as structural types containing other `Pod` types.
|
as well as structural types containing other `Pod` types.
|
||||||
`'static`
|
`'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
|
this can be a useful guarantee for code
|
||||||
that breaks borrowing assumptions
|
that breaks borrowing assumptions
|
||||||
using [`unsafe` operations](#unsafe-functions).
|
using [`unsafe` operations](#unsafe-functions).
|
||||||
|
@ -3417,14 +3417,14 @@ frame they are allocated within.
|
||||||
### Memory ownership
|
### Memory ownership
|
||||||
|
|
||||||
A task owns all memory it can *safely* reach through local variables,
|
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,
|
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.
|
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",
|
This is statically guaranteed by the combined use of "move semantics",
|
||||||
and the compiler-checked _meaning_ of the `Send` trait:
|
and the compiler-checked _meaning_ of the `Send` trait:
|
||||||
it is only instantiated for (transitively) sendable kinds of data constructor and pointers,
|
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
|
When a stack frame is exited, its local allocations are all released, and its
|
||||||
references to boxes (both managed and owned) are dropped.
|
references to boxes (both managed and owned) are dropped.
|
||||||
|
@ -3569,7 +3569,7 @@ These include:
|
||||||
- simple locks and semaphores
|
- simple locks and semaphores
|
||||||
|
|
||||||
When such facilities carry values, the values are restricted to the [`Send` type-kind](#type-kinds).
|
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;
|
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.
|
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
|
*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
|
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
|
any object, and the compiler verifies that it cannot outlive the lifetime of
|
||||||
the object.
|
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
|
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
|
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
|
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 }
|
# 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
|
In the case of the boxes `managed_box` and `owned_box`, however, no
|
||||||
explicit action is necessary. The compiler will automatically convert
|
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
|
`&point`. This is another form of borrowing; in this case, the
|
||||||
contents of the managed/owned box are being lent out.
|
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
|
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
|
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
|
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.
|
make full use of it again.
|
||||||
|
|
||||||
For a more in-depth explanation of borrowed pointers and lifetimes, read the
|
For a more in-depth explanation of references and lifetimes, read the
|
||||||
[lifetimes and borrowed pointer tutorial][lifetimes].
|
[references and lifetimes guide][lifetimes].
|
||||||
|
|
||||||
## Freezing
|
## Freezing
|
||||||
|
|
||||||
|
@ -1622,8 +1623,7 @@ defined in [`std::vec`] and [`std::str`].
|
||||||
|
|
||||||
# Ownership escape hatches
|
# Ownership escape hatches
|
||||||
|
|
||||||
Ownership can cleanly describe tree-like data structures, and borrowed pointers provide non-owning
|
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
|
||||||
references. However, more flexibility is often desired and Rust provides ways to escape from strict
|
|
||||||
single parent ownership.
|
single parent ownership.
|
||||||
|
|
||||||
The standard library provides the `std::rc::Rc` pointer type to express *shared ownership* over a
|
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)
|
# Rectangle(Point, Point)
|
||||||
# }
|
# }
|
||||||
impl Shape {
|
impl Shape {
|
||||||
fn draw_borrowed(&self) { ... }
|
fn draw_reference(&self) { ... }
|
||||||
fn draw_managed(@self) { ... }
|
fn draw_managed(@self) { ... }
|
||||||
fn draw_owned(~self) { ... }
|
fn draw_owned(~self) { ... }
|
||||||
fn draw_value(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_managed();
|
||||||
(~s).draw_owned();
|
(~s).draw_owned();
|
||||||
(&s).draw_borrowed();
|
(&s).draw_reference();
|
||||||
s.draw_value();
|
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
|
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) { }
|
# fn draw_circle(p: Point, f: f64) { }
|
||||||
|
@ -1907,27 +1907,27 @@ to a borrowed pointer.
|
||||||
# Rectangle(Point, Point)
|
# Rectangle(Point, Point)
|
||||||
# }
|
# }
|
||||||
# impl Shape {
|
# impl Shape {
|
||||||
# fn draw_borrowed(&self) { ... }
|
# fn draw_reference(&self) { ... }
|
||||||
# fn draw_managed(@self) { ... }
|
# fn draw_managed(@self) { ... }
|
||||||
# fn draw_owned(~self) { ... }
|
# fn draw_owned(~self) { ... }
|
||||||
# fn draw_value(self) { ... }
|
# fn draw_value(self) { ... }
|
||||||
# }
|
# }
|
||||||
# let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
|
# let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
|
||||||
// As with typical function arguments, managed and owned pointers
|
// 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_reference();
|
||||||
(~s).draw_borrowed();
|
(~s).draw_reference();
|
||||||
|
|
||||||
// Unlike typical function arguments, the self value will
|
// Unlike typical function arguments, the self value will
|
||||||
// automatically be referenced ...
|
// automatically be referenced ...
|
||||||
s.draw_borrowed();
|
s.draw_reference();
|
||||||
|
|
||||||
// ... and dereferenced
|
// ... and dereferenced
|
||||||
(& &s).draw_borrowed();
|
(& &s).draw_reference();
|
||||||
|
|
||||||
// ... and dereferenced and borrowed
|
// ... and dereferenced and borrowed
|
||||||
(&@~s).draw_borrowed();
|
(&@~s).draw_reference();
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Implementations may also define standalone (sometimes called "static")
|
Implementations may also define standalone (sometimes called "static")
|
||||||
|
@ -2095,7 +2095,7 @@ and may not be overridden:
|
||||||
|
|
||||||
* `Send` - Sendable types.
|
* `Send` - Sendable types.
|
||||||
Types are sendable
|
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.
|
* `Freeze` - Constant (immutable) types.
|
||||||
These are types that do not contain anything intrinsically mutable.
|
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.
|
* `'static` - Non-borrowed types.
|
||||||
These are types that do not contain any data whose lifetime is bound to
|
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
|
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.
|
have the `'static` lifetime.
|
||||||
|
|
||||||
> ***Note:*** These two traits were referred to as 'kinds' in earlier
|
> ***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 owned traits (`~Trait`) must fulfill the `Send` bound.
|
||||||
* The contents of managed traits (`@Trait`) must fulfill the `'static` 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
|
Consequently, the trait objects themselves automatically fulfill their
|
||||||
respective kind bounds. However, this default behavior can be overridden by
|
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
|
# Markdown files under doc/ that should have their code extracted and run
|
||||||
DOC_TEST_NAMES = tutorial guide-ffi guide-macros guide-lifetimes \
|
DOC_TEST_NAMES = tutorial guide-ffi guide-macros guide-lifetimes \
|
||||||
guide-tasks guide-conditions guide-container guide-pointers \
|
guide-tasks guide-conditions guide-container guide-pointers \
|
||||||
|
complement-cheatsheet \
|
||||||
rust
|
rust
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#define CFG_VERSION GetEnv("CFG_VERSION")
|
#define CFG_VERSION GetEnv("CFG_VERSION")
|
||||||
#define CFG_VERSION_WIN GetEnv("CFG_VERSION_WIN")
|
#define CFG_VERSION_WIN GetEnv("CFG_VERSION_WIN")
|
||||||
|
#define CFG_RELEASE GetEnv("CFG_RELEASE")
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ DisableStartupPrompt=true
|
||||||
|
|
||||||
OutputDir=.\
|
OutputDir=.\
|
||||||
SourceDir=.\
|
SourceDir=.\
|
||||||
OutputBaseFilename=rust-{#CFG_VERSION}-install
|
OutputBaseFilename=rust-{#CFG_RELEASE}-install
|
||||||
DefaultDirName={pf32}\Rust
|
DefaultDirName={pf32}\Rust
|
||||||
|
|
||||||
Compression=lzma2/ultra
|
Compression=lzma2/ultra
|
||||||
|
|
|
@ -60,8 +60,8 @@ impl<A> Future<A> {
|
||||||
|
|
||||||
pub fn get_ref<'a>(&'a mut self) -> &'a A {
|
pub fn get_ref<'a>(&'a mut self) -> &'a A {
|
||||||
/*!
|
/*!
|
||||||
* Executes the future's closure and then returns a borrowed
|
* Executes the future's closure and then returns a reference
|
||||||
* pointer to the result. The borrowed pointer lasts as long as
|
* to the result. The reference lasts as long as
|
||||||
* the future.
|
* the future.
|
||||||
*/
|
*/
|
||||||
match self.state {
|
match self.state {
|
||||||
|
|
|
@ -431,7 +431,7 @@ struct RWLockInner {
|
||||||
// (or reader/downgrader) race.
|
// (or reader/downgrader) race.
|
||||||
// By the way, if we didn't care about the assert in the read unlock path,
|
// 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,
|
// 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,
|
read_mode: bool,
|
||||||
// The only way the count flag is ever accessed is with xadd. Since it is
|
// 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
|
// a read-modify-write operation, multiple xadds on different cores will
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
#[license = "MIT/ASL2"];
|
#[license = "MIT/ASL2"];
|
||||||
#[crate_type = "rlib"];
|
#[crate_type = "rlib"];
|
||||||
#[crate_type = "dylib"];
|
#[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.
|
// NB this does *not* include globs, please keep it that way.
|
||||||
#[feature(macro_rules)];
|
#[feature(macro_rules)];
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
#[license = "MIT/ASL2"];
|
#[license = "MIT/ASL2"];
|
||||||
#[crate_type = "rlib"];
|
#[crate_type = "rlib"];
|
||||||
#[crate_type = "dylib"];
|
#[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
|
// NB this crate explicitly does *not* allow glob imports, please seriously
|
||||||
// consider whether they're needed before adding that feature here (the
|
// 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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
The Rust compiler.
|
||||||
|
|
||||||
|
# Note
|
||||||
|
|
||||||
|
This API is completely unstable and subject to change.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#[crate_id = "rustc#0.9"];
|
#[crate_id = "rustc#0.9"];
|
||||||
#[comment = "The Rust compiler"];
|
#[comment = "The Rust compiler"];
|
||||||
#[license = "MIT/ASL2"];
|
#[license = "MIT/ASL2"];
|
||||||
#[crate_type = "dylib"];
|
#[crate_type = "dylib"];
|
||||||
#[crate_type = "rlib"];
|
#[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)];
|
#[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
|
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
|
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
|
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
|
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
|
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
|
The loan states that the expression `(*x).f` has been loaned as
|
||||||
mutable for the lifetime `'a`. Because the loan is mutable, that means
|
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
|
that the value `(*x).f` may be mutated via the newly created reference
|
||||||
pointer (and *only* via that pointer). This is reflected in the
|
(and *only* via that pointer). This is reflected in the
|
||||||
restrictions `RS` that accompany the loan.
|
restrictions `RS` that accompany the loan.
|
||||||
|
|
||||||
The first restriction `((*x).f, [MUTATE, CLAIM, FREEZE])` states that
|
The first restriction `((*x).f, [MUTATE, CLAIM, FREEZE])` states that
|
||||||
the lender may not mutate nor freeze `(*x).f`. Mutation is illegal
|
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
|
because `(*x).f` is only supposed to be mutated via the new reference,
|
||||||
pointer, not by mutating the original path `(*x).f`. Freezing is
|
not by mutating the original path `(*x).f`. Freezing is
|
||||||
illegal because the path now has an `&mut` alias; so even if we the
|
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
|
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
|
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
|
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:
|
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
|
if the user were to assign to (or freeze) `*x`, they would indirectly
|
||||||
overwrite (or freeze) `(*x).f`, and thus invalidate the borrowed
|
overwrite (or freeze) `(*x).f`, and thus invalidate the reference
|
||||||
pointer that was created. In general it holds that when a path is
|
that was created. In general it holds that when a path is
|
||||||
lent, restrictions are issued for all the owning prefixes of that
|
lent, restrictions are issued for all the owning prefixes of that
|
||||||
path. In this case, the path `*x` owns the path `(*x).f` and,
|
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`.
|
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
|
of the resulting pointer. Given those, `gather_loans` applies three
|
||||||
validity tests:
|
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
|
compatible with the mutability of `LV` (i.e., not borrowing immutable
|
||||||
data as mutable).
|
data as mutable).
|
||||||
|
|
||||||
|
@ -380,9 +380,9 @@ of its owner:
|
||||||
TYPE(LV) = ~Ty
|
TYPE(LV) = ~Ty
|
||||||
LIFETIME(LV, LT, MQ)
|
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
|
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`
|
lifetime. Therefore, the borrow is valid so long as the lifetime `LT`
|
||||||
of the borrow is shorter than the lifetime `LT'` of the pointer
|
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
|
(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
|
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
|
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.
|
location is aliasable.
|
||||||
|
|
||||||
If the conditions of `L-Deref-Managed-Imm-User-Root` are not met, then
|
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
|
//! &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
|
//! variable `v` that hosts it. Note that this doesn't come up
|
||||||
//! with immutable `&` pointers, because borrows of such pointers
|
//! with immutable `&` pointers, because borrows of such pointers
|
||||||
//! do not require restrictions and hence do not cause a loan.
|
//! 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) => {
|
err_out_of_scope(super_scope, sub_scope) => {
|
||||||
note_and_explain_region(
|
note_and_explain_region(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
"borrowed pointer must be valid for ",
|
"reference must be valid for ",
|
||||||
sub_scope,
|
sub_scope,
|
||||||
"...");
|
"...");
|
||||||
note_and_explain_region(
|
note_and_explain_region(
|
||||||
|
|
|
@ -192,7 +192,7 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
|
||||||
ExprAddrOf(..) => {
|
ExprAddrOf(..) => {
|
||||||
sess.span_err(
|
sess.span_err(
|
||||||
e.span,
|
e.span,
|
||||||
"borrowed pointers in constants may only refer to \
|
"references in constants may only refer to \
|
||||||
immutable values");
|
immutable values");
|
||||||
},
|
},
|
||||||
ExprVstore(_, ExprVstoreUniq) |
|
ExprVstore(_, ExprVstoreUniq) |
|
||||||
|
|
|
@ -33,7 +33,7 @@ use syntax::visit::Visitor;
|
||||||
// send: Things that can be sent on channels or included in spawned closures.
|
// send: Things that can be sent on channels or included in spawned closures.
|
||||||
// freeze: Things thare are deeply immutable. They are guaranteed never to
|
// freeze: Things thare are deeply immutable. They are guaranteed never to
|
||||||
// change, and can be safely shared without copying between tasks.
|
// 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
|
// Send includes scalar types as well as classes and unique types containing
|
||||||
// only sendable types.
|
// 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) {
|
if !ty::type_is_static(tcx, ty) {
|
||||||
match ty::get(ty).sty {
|
match ty::get(ty).sty {
|
||||||
ty::ty_param(..) => {
|
ty::ty_param(..) => {
|
||||||
tcx.sess.span_err(sp, "value may contain borrowed \
|
tcx.sess.span_err(sp, "value may contain references; \
|
||||||
pointers; add `'static` bound");
|
add `'static` bound");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
tcx.sess.span_err(sp, "value may contain borrowed \
|
tcx.sess.span_err(sp, "value may contain references");
|
||||||
pointers");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
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
|
/// 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
|
/// trait like `a as trait<'r>`, regionck already ensures that any references
|
||||||
/// pointers that appear in the type of `a` are bounded by `'r` (ed.: rem
|
/// that appear in the type of `a` are bounded by `'r` (ed.: rem
|
||||||
/// FIXME(#5723)). However, it is possible that there are *type parameters*
|
/// 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
|
/// within them. We have to guarantee that the regions which appear in those
|
||||||
/// type parameters are not obscured.
|
/// 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
|
/// (1) The trait instance cannot escape the current fn. This is
|
||||||
/// guaranteed if the region bound `&r` is some scope within the fn
|
/// 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
|
/// found within the type parameter, they must enclose the fn body
|
||||||
/// itself.
|
/// itself.
|
||||||
///
|
///
|
||||||
/// (2) The type parameter appears in the type of the trait. For
|
/// (2) The type parameter appears in the type of the trait. For
|
||||||
/// example, if the type parameter is `T` and the trait type is
|
/// 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>`.
|
/// appear in `deque<T>`.
|
||||||
///
|
///
|
||||||
/// (3) The type parameter is sendable (and therefore does not contain
|
/// (3) The type parameter is sendable (and therefore does not contain
|
||||||
/// borrowed ptrs).
|
/// references).
|
||||||
///
|
///
|
||||||
/// FIXME(#5723)---This code should probably move into regionck.
|
/// FIXME(#5723)---This code should probably move into regionck.
|
||||||
pub fn check_cast_for_escaping_regions(
|
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)) {
|
// if !target_regions.iter().any(|t_r| is_subregion_of(cx, *t_r, r)) {
|
||||||
// cx.tcx.sess.span_err(
|
// cx.tcx.sess.span_err(
|
||||||
// source_span,
|
// source_span,
|
||||||
// format!("source contains borrowed pointer with lifetime \
|
// format!("source contains reference with lifetime \
|
||||||
// not found in the target type `{}`",
|
// not found in the target type `{}`",
|
||||||
// ty_to_str(cx.tcx, target_ty)));
|
// ty_to_str(cx.tcx, target_ty)));
|
||||||
// note_and_explain_region(
|
// note_and_explain_region(
|
||||||
|
|
|
@ -612,7 +612,7 @@ impl VisitContext {
|
||||||
self.use_receiver(receiver_expr);
|
self.use_receiver(receiver_expr);
|
||||||
|
|
||||||
// for overloaded operatrs, we are always passing in a
|
// 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() {
|
for arg_expr in arg_exprs.iter() {
|
||||||
self.use_expr(*arg_expr, Read);
|
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
|
* 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
|
* 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 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
|
* The reason we compute type contents and not kinds is that it is
|
||||||
* easier for me (nmatsakis) to think about what is contained within
|
* 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)
|
mutbl: ast::Mutability)
|
||||||
-> TypeContents {
|
-> TypeContents {
|
||||||
/*!
|
/*!
|
||||||
* Type contents due to containing a borrowed pointer
|
* Type contents due to containing a reference
|
||||||
* with the region `region` and borrow kind `bk`
|
* with the region `region` and borrow kind `bk`
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -789,10 +789,10 @@ fn constrain_regions_in_type(
|
||||||
pub mod guarantor {
|
pub mod guarantor {
|
||||||
/*!
|
/*!
|
||||||
* The routines in this module are aiming to deal with the case
|
* The routines in this module are aiming to deal with the case
|
||||||
* where a the contents of a borrowed pointer are re-borrowed.
|
* where a the contents of a reference are re-borrowed.
|
||||||
* Imagine you have a borrowed pointer `b` with lifetime L1 and
|
* Imagine you have a reference `b` with lifetime L1 and
|
||||||
* you have an expression `&*b`. The result of this borrow will
|
* 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
|
* inference variable). The borrow checker is going to enforce
|
||||||
* the constraint that L2 < L1, because otherwise you are
|
* the constraint that L2 < L1, because otherwise you are
|
||||||
* re-borrowing data for a lifetime larger than the original loan.
|
* re-borrowing data for a lifetime larger than the original loan.
|
||||||
|
@ -815,15 +815,15 @@ pub mod guarantor {
|
||||||
* a borrow.
|
* a borrow.
|
||||||
*
|
*
|
||||||
* The key point here is that when you are borrowing a value that
|
* The key point here is that when you are borrowing a value that
|
||||||
* is "guaranteed" by a borrowed pointer, you must link the
|
* is "guaranteed" by a reference, you must link the
|
||||||
* lifetime of that borrowed pointer (L1, here) to the lifetime of
|
* lifetime of that reference (L1, here) to the lifetime of
|
||||||
* the borrow itself (L2). What do I mean by "guaranteed" by a
|
* the borrow itself (L2). What do I mean by "guaranteed" by a
|
||||||
* borrowed pointer? I mean any data that is reached by first
|
* reference? I mean any data that is reached by first
|
||||||
* dereferencing a borrowed pointer and then either traversing
|
* dereferencing a reference and then either traversing
|
||||||
* interior offsets or owned pointers. We say that the guarantor
|
* 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
|
* 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.
|
* contents.
|
||||||
*
|
*
|
||||||
* NB: I really wanted to use the `mem_categorization` code here
|
* NB: I really wanted to use the `mem_categorization` code here
|
||||||
|
@ -953,7 +953,7 @@ pub mod guarantor {
|
||||||
guarantor: Option<ty::Region>) {
|
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).
|
* to the lifetime of its guarantor (if any).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1134,7 +1134,7 @@ pub mod guarantor {
|
||||||
Some(ty::AutoBorrowFn(r)) |
|
Some(ty::AutoBorrowFn(r)) |
|
||||||
Some(ty::AutoBorrowObj(r, _)) => {
|
Some(ty::AutoBorrowObj(r, _)) => {
|
||||||
// If there is an autoref, then the result of this
|
// 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.guarantor = None;
|
||||||
expr_ct.cat.pointer = BorrowedPointer(r);
|
expr_ct.cat.pointer = BorrowedPointer(r);
|
||||||
debug!("autoref, cat={:?}", expr_ct.cat);
|
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
|
* for each function just before we check the body of that
|
||||||
* function, looking for types where you have a borrowed
|
* function, looking for types where you have a borrowed
|
||||||
* pointer to other borrowed data (e.g., `&'a &'b [uint]`.
|
* 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`.
|
* point at, so we can assume that `'a <= 'b`.
|
||||||
*
|
*
|
||||||
* Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
|
* Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
|
||||||
|
|
|
@ -20,8 +20,8 @@ but not in representation (so actual subtyping is inappropriate).
|
||||||
|
|
||||||
## Reborrowing
|
## Reborrowing
|
||||||
|
|
||||||
Note that if we are expecting a borrowed pointer, we will *reborrow*
|
Note that if we are expecting a reference, we will *reborrow*
|
||||||
even if the argument provided was already a borrowed pointer. This is
|
even if the argument provided was already a reference. This is
|
||||||
useful for freezing mut/const things (that is, when the expected is &T
|
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
|
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
|
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);
|
let a_unsafe = ty::mk_ptr(self.get_ref().infcx.tcx, mt_a);
|
||||||
if_ok!(self.subtype(a_unsafe, b));
|
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
|
// representation, we still register an AutoDerefRef so that
|
||||||
// regionck knows that the region for `a` must be valid here
|
// regionck knows that the region for `a` must be valid here
|
||||||
Ok(Some(@AutoDerefRef(AutoDerefRef {
|
Ok(Some(@AutoDerefRef(AutoDerefRef {
|
||||||
|
|
|
@ -226,11 +226,11 @@ impl ErrorReporting for InferCtxt {
|
||||||
infer::Reborrow(span) => {
|
infer::Reborrow(span) => {
|
||||||
self.tcx.sess.span_err(
|
self.tcx.sess.span_err(
|
||||||
span,
|
span,
|
||||||
"lifetime of borrowed pointer outlines \
|
"lifetime of reference outlines \
|
||||||
lifetime of borrowed content...");
|
lifetime of borrowed content...");
|
||||||
note_and_explain_region(
|
note_and_explain_region(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
"...the borrowed pointer is valid for ",
|
"...the reference is valid for ",
|
||||||
sub,
|
sub,
|
||||||
"...");
|
"...");
|
||||||
note_and_explain_region(
|
note_and_explain_region(
|
||||||
|
@ -351,7 +351,7 @@ impl ErrorReporting for InferCtxt {
|
||||||
infer::AddrOf(span) => {
|
infer::AddrOf(span) => {
|
||||||
self.tcx.sess.span_err(
|
self.tcx.sess.span_err(
|
||||||
span,
|
span,
|
||||||
"borrowed pointer is not valid \
|
"reference is not valid \
|
||||||
at the time of borrow");
|
at the time of borrow");
|
||||||
note_and_explain_region(
|
note_and_explain_region(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
|
@ -362,7 +362,7 @@ impl ErrorReporting for InferCtxt {
|
||||||
infer::AutoBorrow(span) => {
|
infer::AutoBorrow(span) => {
|
||||||
self.tcx.sess.span_err(
|
self.tcx.sess.span_err(
|
||||||
span,
|
span,
|
||||||
"automatically borrowed pointer is not valid \
|
"automatically reference is not valid \
|
||||||
at the time of borrow");
|
at the time of borrow");
|
||||||
note_and_explain_region(
|
note_and_explain_region(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
|
@ -532,7 +532,7 @@ impl ErrorReportingHelpers for InferCtxt {
|
||||||
infer::Reborrow(span) => {
|
infer::Reborrow(span) => {
|
||||||
self.tcx.sess.span_note(
|
self.tcx.sess.span_note(
|
||||||
span,
|
span,
|
||||||
"...so that borrowed pointer does not outlive \
|
"...so that reference does not outlive \
|
||||||
borrowed content");
|
borrowed content");
|
||||||
}
|
}
|
||||||
infer::InfStackClosure(span) => {
|
infer::InfStackClosure(span) => {
|
||||||
|
@ -586,13 +586,13 @@ impl ErrorReportingHelpers for InferCtxt {
|
||||||
infer::AddrOf(span) => {
|
infer::AddrOf(span) => {
|
||||||
self.tcx.sess.span_note(
|
self.tcx.sess.span_note(
|
||||||
span,
|
span,
|
||||||
"...so that borrowed pointer is valid \
|
"...so that reference is valid \
|
||||||
at the time of borrow");
|
at the time of borrow");
|
||||||
}
|
}
|
||||||
infer::AutoBorrow(span) => {
|
infer::AutoBorrow(span) => {
|
||||||
self.tcx.sess.span_note(
|
self.tcx.sess.span_note(
|
||||||
span,
|
span,
|
||||||
"...so that automatically borrowed pointer is valid \
|
"...so that automatically reference is valid \
|
||||||
at the time of borrow");
|
at the time of borrow");
|
||||||
}
|
}
|
||||||
infer::BindingTypeIsNotValidAtDecl(span) => {
|
infer::BindingTypeIsNotValidAtDecl(span) => {
|
||||||
|
|
|
@ -157,7 +157,7 @@ pub enum SubregionOrigin {
|
||||||
// Invocation of closure must be within its lifetime
|
// Invocation of closure must be within its lifetime
|
||||||
InvokeClosure(Span),
|
InvokeClosure(Span),
|
||||||
|
|
||||||
// Dereference of borrowed pointer must be within its lifetime
|
// Dereference of reference must be within its lifetime
|
||||||
DerefPointer(Span),
|
DerefPointer(Span),
|
||||||
|
|
||||||
// Closure bound must not outlive captured free variables
|
// Closure bound must not outlive captured free variables
|
||||||
|
@ -170,7 +170,7 @@ pub enum SubregionOrigin {
|
||||||
// relating `'a` to `'b`
|
// relating `'a` to `'b`
|
||||||
RelateObjectBound(Span),
|
RelateObjectBound(Span),
|
||||||
|
|
||||||
// Creating a pointer `b` to contents of another borrowed pointer
|
// Creating a pointer `b` to contents of another reference
|
||||||
Reborrow(Span),
|
Reborrow(Span),
|
||||||
|
|
||||||
// (&'a &'b T) where a >= b
|
// (&'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
|
all arguments have been evaluated. There is a corresponding lifetime
|
||||||
`'b_call` for the execution of `inc()`. If we wanted to be precise
|
`'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
|
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.
|
will not be dereferenced except during the execution itself.
|
||||||
|
|
||||||
However, this model by itself is not sound. The reason is that
|
However, this model by itself is not sound. The reason is that
|
||||||
while the two borrowed pointers that are created will never be used
|
while the two references that are created will never be used
|
||||||
simultaneously, it is still true that the first borrowed pointer is
|
simultaneously, it is still true that the first reference is
|
||||||
*created* before the second argument is evaluated, and so even though
|
*created* before the second argument is evaluated, and so even though
|
||||||
it will not be *dereferenced* during the evaluation of the second
|
it will not be *dereferenced* during the evaluation of the second
|
||||||
argument, it can still be *invalidated* by that evaluation. Consider
|
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.
|
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
|
Eventually I would like to include them, but we will have to make the
|
||||||
borrow checker handle this situation correctly. In particular, if
|
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
|
the borrow expression, we must issue sufficient restrictions to ensure
|
||||||
that the pointee remains valid.
|
that the pointee remains valid.
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ use syntax::opt_vec::OptVec;
|
||||||
|
|
||||||
/// Defines strategies for handling regions that are omitted. For
|
/// Defines strategies for handling regions that are omitted. For
|
||||||
/// example, if one writes the type `&Foo`, then the lifetime of of
|
/// 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`
|
/// type, the generic functions in astconv will invoke `anon_regions`
|
||||||
/// on the provided region-scope to decide how to translate this
|
/// on the provided region-scope to decide how to translate this
|
||||||
/// omitted region.
|
/// omitted region.
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//! Borrowed pointer utilities
|
//! Utilities for references
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
|
|
|
@ -64,7 +64,7 @@ pub unsafe fn transmute<L, G>(thing: L) -> G {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }
|
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]
|
#[inline]
|
||||||
pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T {
|
pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T {
|
||||||
transmute(ptr)
|
transmute(ptr)
|
||||||
|
@ -82,7 +82,7 @@ pub unsafe fn transmute_immut_unsafe<T,P:RawPtr<T>>(ptr: P) -> *T {
|
||||||
transmute(ptr)
|
transmute(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Coerce a borrowed mutable pointer to have an arbitrary associated region.
|
/// Coerce a mutable reference to have an arbitrary associated region.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn transmute_mut_region<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
|
pub unsafe fn transmute_mut_region<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
|
||||||
transmute(ptr)
|
transmute(ptr)
|
||||||
|
|
|
@ -59,7 +59,7 @@ impl<T> Clone for @T {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Clone for &'a T {
|
impl<'a, T> Clone for &'a T {
|
||||||
/// Return a shallow copy of the borrowed pointer.
|
/// Return a shallow copy of the reference.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> &'a T { *self }
|
fn clone(&self) -> &'a T { *self }
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
//! `std` includes modules corresponding to each of the integer types,
|
//! `std` includes modules corresponding to each of the integer types,
|
||||||
//! each of the floating point types, the `bool` type, tuples, characters,
|
//! each of the floating point types, the `bool` type, tuples, characters,
|
||||||
//! strings (`str`), vectors (`vec`), managed boxes (`managed`), owned
|
//! 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`),
|
//! Additionally, `std` provides pervasive types (`option` and `result`),
|
||||||
//! task creation and communication primitives (`task`, `comm`), platform
|
//! task creation and communication primitives (`task`, `comm`), platform
|
||||||
//! abstractions (`os` and `path`), basic I/O abstractions (`io`), common
|
//! abstractions (`os` and `path`), basic I/O abstractions (`io`), common
|
||||||
|
|
|
@ -71,7 +71,7 @@ traits from other modules. Some notable examples:
|
||||||
## Iteration
|
## Iteration
|
||||||
|
|
||||||
The method `iter()` returns an iteration value for a vector or a vector slice.
|
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`.
|
type of the vector is `int`, the element type of the iterator is `&int`.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
|
|
@ -371,7 +371,7 @@ pub enum Pat_ {
|
||||||
PatTup(~[@Pat]),
|
PatTup(~[@Pat]),
|
||||||
PatBox(@Pat),
|
PatBox(@Pat),
|
||||||
PatUniq(@Pat),
|
PatUniq(@Pat),
|
||||||
PatRegion(@Pat), // borrowed pointer pattern
|
PatRegion(@Pat), // reference pattern
|
||||||
PatLit(@Expr),
|
PatLit(@Expr),
|
||||||
PatRange(@Expr, @Expr),
|
PatRange(@Expr, @Expr),
|
||||||
// [a, b, ..i, y, z] is represented as
|
// [a, b, ..i, y, z] is represented as
|
||||||
|
|
|
@ -26,7 +26,7 @@ Supported features (fairly exhaustive):
|
||||||
requires an explicit `Eq` bound at the
|
requires an explicit `Eq` bound at the
|
||||||
moment. (`TraitDef.additional_bounds`)
|
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)`,
|
e.g. deriving TotalEq/TotalOrd/Clone don't work on `struct A(&int)`,
|
||||||
because of how the auto-dereferencing happens.
|
because of how the auto-dereferencing happens.
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,23 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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"];
|
#[crate_id = "syntax#0.9"];
|
||||||
#[license = "MIT/ASL2"];
|
#[license = "MIT/ASL2"];
|
||||||
#[crate_type = "dylib"];
|
#[crate_type = "dylib"];
|
||||||
#[crate_type = "rlib"];
|
#[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)];
|
#[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
|
// 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 {
|
pub struct StrInterner {
|
||||||
priv map: @RefCell<HashMap<@str, Name>>,
|
priv map: @RefCell<HashMap<@str, Name>>,
|
||||||
priv vect: @RefCell<~[@str]>,
|
priv vect: @RefCell<~[@str]>,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#[feature(managed_boxes)];
|
#[feature(managed_boxes)];
|
||||||
|
|
||||||
fn f<T>(x: T) -> @T {
|
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 {
|
fn g<T:'static>(x: T) -> @T {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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;
|
use std::local_data;
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ impl<T:Clone> foo for T {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_foo<T:Clone>(t: T) {
|
fn to_foo<T:Clone>(t: T) {
|
||||||
// This version is ok because, although T may contain borrowed
|
// This version is ok because, although T may contain references
|
||||||
// pointers, it never escapes the fn body. We know this because
|
// it never escapes the fn body. We know this because
|
||||||
// the type of foo includes a region which will be resolved to
|
// the type of foo includes a region which will be resolved to
|
||||||
// the fn body itself.
|
// the fn body itself.
|
||||||
let v = &3;
|
let v = &3;
|
||||||
|
@ -34,15 +34,15 @@ fn to_foo<T:Clone>(t: T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_foo_2<T:Clone>(t: T) -> @foo {
|
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
|
// as part of the returned foo value
|
||||||
struct F<T> { f: T }
|
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 {
|
fn to_foo_3<T:Clone + 'static>(t: T) -> @foo {
|
||||||
// OK---T may escape as part of the returned foo value, but it is
|
// 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 }
|
struct F<T> { f: T }
|
||||||
@F {f:t} as @foo
|
@F {f:t} as @foo
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ trait foo { fn foo(&self); }
|
||||||
|
|
||||||
fn to_foo<T:Clone + foo>(t: T) -> @foo {
|
fn to_foo<T:Clone + foo>(t: T) -> @foo {
|
||||||
@t as @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 cannot pack type
|
||||||
//~^^^ ERROR value may contain borrowed pointers
|
//~^^^ ERROR value may contain references
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_foo2<T:Clone + foo + 'static>(t: T) -> @foo {
|
fn to_foo2<T:Clone + foo + 'static>(t: T) -> @foo {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
// xfail-test #5723
|
// xfail-test #5723
|
||||||
|
|
||||||
// Test that you cannot escape a borrowed pointer
|
// Test that you cannot escape a reference
|
||||||
// into a trait.
|
// into a trait.
|
||||||
|
|
||||||
struct ctxt { v: uint }
|
struct ctxt { v: uint }
|
||||||
|
@ -29,7 +29,7 @@ fn make_gc() -> @get_ctxt {
|
||||||
let ctxt = ctxt { v: 22u };
|
let ctxt = ctxt { v: 22u };
|
||||||
let hc = has_ctxt { c: &ctxt };
|
let hc = has_ctxt { c: &ctxt };
|
||||||
return @hc as @get_ctxt;
|
return @hc as @get_ctxt;
|
||||||
//^~ ERROR source contains borrowed pointer
|
//^~ ERROR source contains reference
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -175,10 +175,10 @@ fn main() {
|
||||||
// managed box
|
// managed box
|
||||||
let @aa = @(34, 35);
|
let @aa = @(34, 35);
|
||||||
|
|
||||||
// borrowed pointer
|
// reference
|
||||||
let &bb = &(36, 37);
|
let &bb = &(36, 37);
|
||||||
|
|
||||||
// contained borrowed pointer
|
// contained reference
|
||||||
let (&cc, _) = (&38, 39);
|
let (&cc, _) = (&38, 39);
|
||||||
|
|
||||||
// unique pointer
|
// unique pointer
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct AsciiArt {
|
||||||
priv lines: ~[~[char]],
|
priv lines: ~[~[char]],
|
||||||
|
|
||||||
// This struct can be quite large so we'll disable copying: developers need
|
// 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 {
|
impl Drop for AsciiArt {
|
||||||
|
|
|
@ -9,12 +9,12 @@
|
||||||
// except according to those terms.
|
// 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
|
A function which takes a reference to a trait and returns a
|
||||||
struct with that borrowed pointer results in an ICE.
|
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.
|
to traits.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue