Skip to content

Commit 6143400

Browse files
committed
auto merge of #10589 : thestinger/rust/doc, r=pcwalton
This replaces the old section on managed pointers because the syntax is going to be removed and it's currently feature gated so the examples don't work out-of-the-box. Dynamic mutability coverage can be added after the `Mut<T>` work has landed.
2 parents 76d4848 + c06ce4c commit 6143400

File tree

1 file changed

+47
-48
lines changed

1 file changed

+47
-48
lines changed

doc/tutorial.md

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -890,9 +890,7 @@ calling the destructor, and the owner determines whether the object is mutable.
890890

891891
Ownership is recursive, so mutability is inherited recursively and a destructor
892892
destroys the contained tree of owned objects. Variables are top-level owners
893-
and destroy the contained object when they go out of scope. A box managed by
894-
the garbage collector starts a new ownership tree, and the destructor is called
895-
when it is collected.
893+
and destroy the contained object when they go out of scope.
896894

897895
~~~~
898896
// the struct owns the objects contained in the `x` and `y` fields
@@ -1009,51 +1007,6 @@ let mut s = r; // box becomes mutable
10091007
let t = s; // box becomes immutable
10101008
~~~~
10111009

1012-
# Managed boxes
1013-
1014-
A managed box (`@`) is a heap allocation with the lifetime managed by a
1015-
task-local garbage collector. It will be destroyed at some point after there
1016-
are no references left to the box, no later than the end of the task. Managed
1017-
boxes lack an owner, so they start a new ownership tree and don't inherit
1018-
mutability. They do own the contained object, and mutability is defined by the
1019-
type of the managed box (`@` or `@mut`). An object containing a managed box is
1020-
not `Owned`, and can't be sent between tasks.
1021-
1022-
~~~~
1023-
let a = @5; // immutable
1024-
1025-
let mut b = @5; // mutable variable, immutable box
1026-
b = @10;
1027-
1028-
let c = @mut 5; // immutable variable, mutable box
1029-
*c = 10;
1030-
1031-
let mut d = @mut 5; // mutable variable, mutable box
1032-
*d += 5;
1033-
d = @mut 15;
1034-
~~~~
1035-
1036-
A mutable variable and an immutable variable can refer to the same box, given
1037-
that their types are compatible. Mutability of a box is a property of its type,
1038-
however, so for example a mutable handle to an immutable box cannot be
1039-
assigned a reference to a mutable box.
1040-
1041-
~~~~
1042-
let a = @1; // immutable box
1043-
let b = @mut 2; // mutable box
1044-
1045-
let mut c : @int; // declare a variable with type managed immutable int
1046-
let mut d : @mut int; // and one of type managed mutable int
1047-
1048-
c = a; // box type is the same, okay
1049-
d = b; // box type is the same, okay
1050-
~~~~
1051-
1052-
~~~~ {.xfail-test}
1053-
// but b cannot be assigned to c, or a to d
1054-
c = b; // error
1055-
~~~~
1056-
10571010
# Borrowed pointers
10581011

10591012
Rust's borrowed pointers are a general purpose reference type. In contrast with
@@ -1347,6 +1300,52 @@ defined in [`std::vec`] and [`std::str`].
13471300
[`std::vec`]: std/vec/index.html
13481301
[`std::str`]: std/str/index.html
13491302
1303+
# Ownership escape hatches
1304+
1305+
Ownership can cleanly describe tree-like data structures, and borrowed pointers provide non-owning
1306+
references. However, more flexibility is often desired and Rust provides ways to escape from strict
1307+
single parent ownership.
1308+
1309+
The standard library provides the `std::rc::Rc` pointer type to express *shared ownership* over a
1310+
reference counted box. As soon as all of the `Rc` pointers go out of scope, the box and the
1311+
contained value are destroyed.
1312+
1313+
~~~
1314+
use std::rc::Rc;
1315+
1316+
// A fixed-size array allocated in a reference-counted box
1317+
let x = Rc::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
1318+
let y = x.clone(); // a new owner
1319+
let z = x; // this moves `x` into `z`, rather than creating a new owner
1320+
1321+
assert_eq!(*z.borrow(), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
1322+
1323+
let mut a = Rc::new([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]); // the variable is mutable, but not the box
1324+
a = z;
1325+
~~~
1326+
1327+
A garbage collected pointer is provided via `std::gc::Gc`, with a task-local garbage collector
1328+
having ownership of the box. It allows the creation of cycles, and the individual `Gc` pointers do
1329+
not have a destructor.
1330+
1331+
~~~
1332+
use std::gc::Gc;
1333+
1334+
// A fixed-size array allocated in a garbage-collected box
1335+
let x = Gc::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
1336+
let y = x; // does not perform a move, unlike with `Rc`
1337+
let z = x;
1338+
1339+
assert_eq!(*z.borrow(), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
1340+
~~~
1341+
1342+
With shared ownership, mutability cannot be inherited so the boxes are always immutable. However,
1343+
it's possible to use *dynamic* mutability via types like `std::cell::Cell` where freezing is handled
1344+
via dynamic checks and can fail at runtime.
1345+
1346+
The `Rc` and `Gc` types are not sendable, so they cannot be used to share memory between tasks. Safe
1347+
immutable and mutable shared memory is provided by the `extra::arc` module.
1348+
13501349
# Closures
13511350
13521351
Named functions, like those we've seen so far, may not refer to local

0 commit comments

Comments
 (0)