@@ -890,7 +890,9 @@ calling the destructor, and the owner determines whether the object is mutable.
890
890
891
891
Ownership is recursive, so mutability is inherited recursively and a destructor
892
892
destroys the contained tree of owned objects. Variables are top-level owners
893
- and destroy the contained object when they go out of scope.
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.
894
896
895
897
~~~~
896
898
// the struct owns the objects contained in the `x` and `y` fields
@@ -1007,6 +1009,51 @@ let mut s = r; // box becomes mutable
1007
1009
let t = s; // box becomes immutable
1008
1010
~~~~
1009
1011
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
+
1010
1057
# Borrowed pointers
1011
1058
1012
1059
Rust's borrowed pointers are a general purpose reference type. In contrast with
@@ -1300,52 +1347,6 @@ defined in [`std::vec`] and [`std::str`].
1300
1347
[`std::vec`]: std/vec/index.html
1301
1348
[`std::str`]: std/str/index.html
1302
1349
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
-
1349
1350
# Closures
1350
1351
1351
1352
Named functions, like those we've seen so far, may not refer to local
0 commit comments