@@ -890,9 +890,7 @@ 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. 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.
896
894
897
895
~~~~
898
896
// the struct owns the objects contained in the `x` and `y` fields
@@ -1009,51 +1007,6 @@ let mut s = r; // box becomes mutable
1009
1007
let t = s; // box becomes immutable
1010
1008
~~~~
1011
1009
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
-
1057
1010
# Borrowed pointers
1058
1011
1059
1012
Rust's borrowed pointers are a general purpose reference type. In contrast with
@@ -1347,6 +1300,52 @@ defined in [`std::vec`] and [`std::str`].
1347
1300
[`std::vec`]: std/vec/index.html
1348
1301
[`std::str`]: std/str/index.html
1349
1302
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
+
1350
1349
# Closures
1351
1350
1352
1351
Named functions, like those we've seen so far, may not refer to local
0 commit comments