@@ -918,9 +918,9 @@ garbage-collected heap to manage all of the objects. This approach is
918
918
straightforward both in concept and in implementation, but has
919
919
significant costs. Languages that take this approach tend to
920
920
aggressively pursue ways to ameliorate allocation costs (think the
921
- Java Virtual Machine). Rust supports this strategy with _ shared
922
- boxes_ : memory allocated on the heap that may be referred to (shared)
923
- by multiple variables .
921
+ Java Virtual Machine). Rust supports this strategy with _ managed
922
+ boxes_ : memory allocated on the heap whose lifetime is managed
923
+ by the garbage collector .
924
924
925
925
By comparison, languages like C++ offer very precise control over
926
926
where objects are allocated. In particular, it is common to put them
@@ -950,16 +950,16 @@ inefficient for large data structures. Because of this, Rust also
950
950
employs a global _ exchange heap_ . Objects allocated in the exchange
951
951
heap have _ ownership semantics_ , meaning that there is only a single
952
952
variable that refers to them. For this reason, they are referred to as
953
- _ unique boxes_ . All tasks may allocate objects on the exchange heap,
953
+ _ owned boxes_ . All tasks may allocate objects on the exchange heap,
954
954
then transfer ownership of those objects to other tasks, avoiding
955
955
expensive copies.
956
956
957
957
## What to be aware of
958
958
959
959
Rust has three "realms" in which objects can be allocated: the stack,
960
960
the local heap, and the exchange heap. These realms have corresponding
961
- pointer types: the borrowed pointer (` &T ` ), the shared box (` @T ` ),
962
- and the unique box (` ~T ` ). These three sigils will appear
961
+ pointer types: the borrowed pointer (` &T ` ), the managed box (` @T ` ),
962
+ and the owned box (` ~T ` ). These three sigils will appear
963
963
repeatedly as we explore the language. Learning the appropriate role
964
964
of each is key to using Rust effectively.
965
965
@@ -978,17 +978,22 @@ records with mutable fields, it can be useful to have a single copy on
978
978
the heap, and refer to that through a pointer.
979
979
980
980
Rust supports several types of pointers. The safe pointer types are
981
- ` @T ` for shared boxes allocated on the local heap, ` ~T ` , for
981
+ ` @T ` for managed boxes allocated on the local heap, ` ~T ` , for
982
982
uniquely-owned boxes allocated on the exchange heap, and ` &T ` , for
983
983
borrowed pointers, which may point to any memory, and whose lifetimes
984
984
are governed by the call stack.
985
985
986
986
All pointer types can be dereferenced with the ` * ` unary operator.
987
987
988
- ## Shared boxes
988
+ > *** Note*** : You may also hear managed boxes referred to as 'shared
989
+ > boxes' or 'shared pointers', and owned boxes as 'unique boxes/pointers'.
990
+ > Borrowed pointers are sometimes called 'region pointers'. The preferred
991
+ > terminology is as presented here.
989
992
990
- Shared boxes are pointers to heap-allocated, garbage collected memory.
991
- Creating a shared box is done by simply applying the unary ` @ `
993
+ ## Managed boxes
994
+
995
+ Managed boxes are pointers to heap-allocated, garbage collected memory.
996
+ Creating a managed box is done by simply applying the unary ` @ `
992
997
operator to an expression. The result of the expression will be boxed,
993
998
resulting in a box of the right type. Copying a shared box, as happens
994
999
during assignment, only copies a pointer, never the contents of the
@@ -1000,22 +1005,24 @@ let y = x; // Copy the pointer, increase refcount
1000
1005
// When x and y go out of scope, refcount goes to 0, box is freed
1001
1006
~~~~
1002
1007
1003
- Shared boxes never cross task boundaries.
1008
+ Managed boxes never cross task boundaries.
1004
1009
1005
- > *** Note:*** shared boxes are currently reclaimed through reference
1010
+ > *** Note:*** managed boxes are currently reclaimed through reference
1006
1011
> counting and cycle collection, but we will switch to a tracing
1007
- > garbage collector.
1012
+ > garbage collector eventually .
1008
1013
1009
- ## Unique boxes
1014
+ ## Owned boxes
1010
1015
1011
- In contrast to shared boxes, unique boxes have a single owner and thus
1012
- two unique boxes may not refer to the same memory. All unique boxes
1013
- across all tasks are allocated on a single _ exchange heap_ , where
1014
- their uniquely owned nature allows them to be passed between tasks.
1016
+ In contrast to maneged boxes, owned boxes have a single owning memory
1017
+ slot and thus two owned boxes may not refer to the same memory. All
1018
+ owned boxes across all tasks are allocated on a single _ exchange
1019
+ heap_ , where their uniquely owned nature allows them to be passed
1020
+ between tasks.
1015
1021
1016
- Because unique boxes are uniquely owned, copying them involves allocating
1017
- a new unique box and duplicating the contents. Copying unique boxes
1018
- is expensive so the compiler will complain if you do.
1022
+ Because owned boxes are uniquely owned, copying them involves allocating
1023
+ a new owned box and duplicating the contents. Copying owned boxes
1024
+ is expensive so the compiler will complain if you do so without writing
1025
+ the word ` copy ` .
1019
1026
1020
1027
~~~~
1021
1028
let x = ~10;
@@ -1029,23 +1036,23 @@ let x = ~10;
1029
1036
let y = copy x;
1030
1037
~~~~
1031
1038
1032
- This is where the 'move' ( ` <- ` ) operator comes in. It is similar to
1033
- ` = ` , but it de-initializes its source. Thus, the unique box can move
1039
+ This is where the 'move' operator comes in. It is similar to
1040
+ ` copy ` , but it de-initializes its source. Thus, the owned box can move
1034
1041
from ` x ` to ` y ` , without violating the constraint that it only has a
1035
1042
single owner (if you used assignment instead of the move operator, the
1036
1043
box would, in principle, be copied).
1037
1044
1038
1045
~~~~
1039
1046
let x = ~10;
1040
- let y <- x;
1047
+ let y = move x;
1041
1048
~~~~
1042
1049
1043
1050
> *** Note:*** this discussion of copying vs moving does not account
1044
1051
> for the "last use" rules that automatically promote copy operations
1045
1052
> to moves. This is an evolving area of the language that will
1046
1053
> continue to change.
1047
1054
1048
- Unique boxes, when they do not contain any shared boxes, can be sent
1055
+ Owned boxes, when they do not contain any managed boxes, can be sent
1049
1056
to other tasks. The sending task will give up ownership of the box,
1050
1057
and won't be able to access it afterwards. The receiving task will
1051
1058
become the sole owner of the box.
@@ -1054,7 +1061,7 @@ become the sole owner of the box.
1054
1061
1055
1062
Rust borrowed pointers are a general purpose reference/pointer type,
1056
1063
similar to the C++ reference type, but guaranteed to point to valid
1057
- memory. In contrast to unique pointers, where the holder of a unique
1064
+ memory. In contrast to owned pointers, where the holder of a unique
1058
1065
pointer is the owner of the pointed-to memory, borrowed pointers never
1059
1066
imply ownership. Pointers may be borrowed from any type, in which case
1060
1067
the pointer is guaranteed not to outlive the value it points to.
@@ -1095,11 +1102,12 @@ fn increase_contents(pt: @mut int) {
1095
1102
}
1096
1103
~~~~
1097
1104
1098
- # Vectors
1105
+ # Vectors and strings
1099
1106
1100
1107
Vectors are a contiguous section of memory containing zero or more
1101
1108
values of the same type. Like other types in Rust, vectors can be
1102
- stored on the stack, the local heap, or the exchange heap.
1109
+ stored on the stack, the local heap, or the exchange heap. Borrowed
1110
+ pointers to vectors are also called 'slices'.
1103
1111
1104
1112
~~~
1105
1113
enum Crayon {
@@ -1108,24 +1116,19 @@ enum Crayon {
1108
1116
BananaMania, Beaver, Bittersweet
1109
1117
}
1110
1118
1111
- // A stack vector of crayons
1119
+ // A fixed-size stack vector
1120
+ let stack_crayons: [Crayon * 3] = [Almond, AntiqueBrass, Apricot];
1121
+
1122
+ // A borrowed pointer to stack allocated vector
1112
1123
let stack_crayons: &[Crayon] = &[Almond, AntiqueBrass, Apricot];
1113
- // A local heap (shared) vector of crayons
1124
+
1125
+ // A local heap (managed) vector of crayons
1114
1126
let local_crayons: @[Crayon] = @[Aquamarine, Asparagus, AtomicTangerine];
1115
- // An exchange heap (unique) vector of crayons
1127
+
1128
+ // An exchange heap (owned) vector of crayons
1116
1129
let exchange_crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];
1117
1130
~~~
1118
1131
1119
- > *** Note:*** Until recently Rust only had unique vectors, using the
1120
- > unadorned ` [] ` syntax for literals. This syntax is still supported
1121
- > but is deprecated. In the future it will probably represent some
1122
- > "reasonable default" vector type.
1123
- >
1124
- > Unique vectors are the currently-recommended vector type for general
1125
- > use as they are the most tested and well-supported by existing
1126
- > libraries. There will be a gradual shift toward using more
1127
- > stack and local vectors in the coming releases.
1128
-
1129
1132
Vector literals are enclosed in square brackets and dereferencing is
1130
1133
also done with square brackets (zero-based):
1131
1134
@@ -1135,24 +1138,24 @@ also done with square brackets (zero-based):
1135
1138
# BananaMania, Beaver, Bittersweet };
1136
1139
# fn draw_scene(c: Crayon) { }
1137
1140
1138
- let crayons = ~ [BananaMania, Beaver, Bittersweet];
1141
+ let crayons = [BananaMania, Beaver, Bittersweet];
1139
1142
match crayons[0] {
1140
1143
Bittersweet => draw_scene(crayons[0]),
1141
1144
_ => ()
1142
1145
}
1143
1146
~~~~
1144
1147
1145
1148
By default, vectors are immutable—you can not replace their elements.
1146
- The type written as ` ~ [mut T]` is a vector with mutable
1147
- elements. Mutable vector literals are written ` ~ [mut]` (empty) or `~ [ mut
1149
+ The type written as ` [mut T] ` is a vector with mutable
1150
+ elements. Mutable vector literals are written ` [mut] ` (empty) or `[ mut
1148
1151
1, 2, 3] ` (with elements).
1149
1152
1150
1153
~~~~
1151
1154
# enum Crayon { Almond, AntiqueBrass, Apricot,
1152
1155
# Aquamarine, Asparagus, AtomicTangerine,
1153
1156
# BananaMania, Beaver, Bittersweet };
1154
1157
1155
- let crayons = ~ [mut BananaMania, Beaver, Bittersweet];
1158
+ let crayons = [mut BananaMania, Beaver, Bittersweet];
1156
1159
crayons[0] = AtomicTangerine;
1157
1160
~~~~
1158
1161
@@ -1183,7 +1186,30 @@ let your_crayons = ~[BananaMania, Beaver, Bittersweet];
1183
1186
my_crayons += your_crayons;
1184
1187
~~~~
1185
1188
1186
- ## Vector and string methods
1189
+ > *** Note:*** The above examples of vector addition use owned
1190
+ > vectors. Some operations on slices and stack vectors are
1191
+ > not well supported yet, owned vectors are often the most
1192
+ > usable.
1193
+
1194
+ Strings are simply vectors of ` [u8] ` , though they have a distinct
1195
+ type. They support most of the same allocation aptions as
1196
+ vectors, though the string literal without a storage sigil, e.g.
1197
+ ` "foo" ` is treated differently than a comparable vector (` [foo] ` ).
1198
+ Where
1199
+
1200
+ ~~~
1201
+ // A plain string is a slice to read-only (static) memory
1202
+ let stack_crayons: &str = "Almond, AntiqueBrass, Apricot";
1203
+
1204
+ // The same thing, but without
1205
+ let stack_crayons: &str = &"Almond, AntiqueBrass, Apricot";
1206
+
1207
+ // A local heap (managed) string
1208
+ let local_crayons: @str = @"Aquamarine, Asparagus, AtomicTangerine";
1209
+
1210
+ // An exchange heap (owned) string
1211
+ let exchange_crayons: ~str = ~"BananaMania, Beaver, Bittersweet";
1212
+ ~~~
1187
1213
1188
1214
Both vectors and strings support a number of useful
1189
1215
[ methods] ( #implementation ) . While we haven't covered methods yet,
@@ -1202,7 +1228,7 @@ brief look at a few common ones.
1202
1228
# fn store_crayon_in_nasal_cavity(i: uint, c: Crayon) { }
1203
1229
# fn crayon_to_str(c: Crayon) -> ~str { ~"" }
1204
1230
1205
- let crayons = ~ [Almond, AntiqueBrass, Apricot];
1231
+ let crayons = & [Almond, AntiqueBrass, Apricot];
1206
1232
1207
1233
// Check the length of the vector
1208
1234
assert crayons.len() == 3;
@@ -1282,15 +1308,15 @@ position and cannot be stored in structures nor returned from
1282
1308
functions. Despite the limitations stack closures are used
1283
1309
pervasively in Rust code.
1284
1310
1285
- ## Shared closures
1311
+ ## Managed closures
1286
1312
1287
1313
When you need to store a closure in a data structure, a stack closure
1288
1314
will not do, since the compiler will refuse to let you store it. For
1289
1315
this purpose, Rust provides a type of closure that has an arbitrary
1290
1316
lifetime, written ` fn@ ` (boxed closure, analogous to the ` @ ` pointer
1291
1317
type described earlier).
1292
1318
1293
- A boxed closure does not directly access its environment, but merely
1319
+ A managed closure does not directly access its environment, but merely
1294
1320
copies out the values that it closes over into a private data
1295
1321
structure. This means that it can not assign to these variables, and
1296
1322
will not 'see' updates to them.
@@ -1315,7 +1341,7 @@ This example uses the long closure syntax, `fn@(s: ~str) ...`,
1315
1341
making the fact that we are declaring a box closure explicit. In
1316
1342
practice boxed closures are usually defined with the short closure
1317
1343
syntax introduced earlier, in which case the compiler will infer
1318
- the type of closure. Thus our boxed closure example could also
1344
+ the type of closure. Thus our managed closure example could also
1319
1345
be written:
1320
1346
1321
1347
~~~~
@@ -1324,13 +1350,13 @@ fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str {
1324
1350
}
1325
1351
~~~~
1326
1352
1327
- ## Unique closures
1353
+ ## Owned closures
1328
1354
1329
- Unique closures, written ` fn~ ` in analogy to the ` ~ ` pointer type,
1355
+ Owned closures, written ` fn~ ` in analogy to the ` ~ ` pointer type,
1330
1356
hold on to things that can safely be sent between
1331
- processes. They copy the values they close over, much like boxed
1357
+ processes. They copy the values they close over, much like managed
1332
1358
closures, but they also 'own' them—meaning no other code can access
1333
- them. Unique closures are used in concurrent code, particularly
1359
+ them. Owned closures are used in concurrent code, particularly
1334
1360
for spawning [ tasks] ( #tasks ) .
1335
1361
1336
1362
## Closure compatibility
@@ -1346,12 +1372,16 @@ that callers have the flexibility to pass whatever they want.
1346
1372
fn call_twice(f: fn()) { f(); f(); }
1347
1373
call_twice(|| { ~"I am an inferred stack closure"; } );
1348
1374
call_twice(fn&() { ~"I am also a stack closure"; } );
1349
- call_twice(fn@() { ~"I am a boxed closure"; });
1350
- call_twice(fn~() { ~"I am a unique closure"; });
1375
+ call_twice(fn@() { ~"I am a managed closure"; });
1376
+ call_twice(fn~() { ~"I am a owned closure"; });
1351
1377
fn bare_function() { ~"I am a plain function"; }
1352
1378
call_twice(bare_function);
1353
1379
~~~~
1354
1380
1381
+ > *** Note:*** Both the syntax and the semantics will be changing
1382
+ > in small ways. At the moment they can be unsound in multiple
1383
+ > scenarios, particularly with non-copyable types.
1384
+
1355
1385
## Do syntax
1356
1386
1357
1387
Closures in Rust are frequently used in combination with higher-order
@@ -1360,7 +1390,7 @@ functions to simulate control structures like `if` and
1360
1390
integers, passing in a pointer to each integer in the vector:
1361
1391
1362
1392
~~~~
1363
- fn each(v: ~ [int], op: fn(v: &int)) {
1393
+ fn each(v: & [int], op: fn(v: &int)) {
1364
1394
let mut n = 0;
1365
1395
while n < v.len() {
1366
1396
op(&v[n]);
@@ -1378,9 +1408,9 @@ closure to provide the final operator argument, we can write it in a
1378
1408
way that has a pleasant, block-like structure.
1379
1409
1380
1410
~~~~
1381
- # fn each(v: ~ [int], op: fn(v: &int)) { }
1411
+ # fn each(v: & [int], op: fn(v: &int)) { }
1382
1412
# fn do_some_work(i: int) { }
1383
- each(~ [1, 2, 3], |n| {
1413
+ each(& [1, 2, 3], |n| {
1384
1414
debug!("%i", *n);
1385
1415
do_some_work(*n);
1386
1416
});
@@ -1390,9 +1420,9 @@ This is such a useful pattern that Rust has a special form of function
1390
1420
call that can be written more like a built-in control structure:
1391
1421
1392
1422
~~~~
1393
- # fn each(v: ~ [int], op: fn(v: &int)) { }
1423
+ # fn each(v: & [int], op: fn(v: &int)) { }
1394
1424
# fn do_some_work(i: int) { }
1395
- do each(~ [1, 2, 3]) |n| {
1425
+ do each(& [1, 2, 3]) |n| {
1396
1426
debug!("%i", *n);
1397
1427
do_some_work(*n);
1398
1428
}
@@ -1438,7 +1468,7 @@ Consider again our `each` function, this time improved to
1438
1468
break early when the iteratee returns ` false ` :
1439
1469
1440
1470
~~~~
1441
- fn each(v: ~ [int], op: fn(v: &int) -> bool) {
1471
+ fn each(v: & [int], op: fn(v: &int) -> bool) {
1442
1472
let mut n = 0;
1443
1473
while n < v.len() {
1444
1474
if !op(&v[n]) {
@@ -1454,7 +1484,7 @@ And using this function to iterate over a vector:
1454
1484
~~~~
1455
1485
# use each = vec::each;
1456
1486
# use println = io::println;
1457
- each(~ [2, 4, 8, 5, 16], |n| {
1487
+ each(& [2, 4, 8, 5, 16], |n| {
1458
1488
if *n % 2 != 0 {
1459
1489
println(~"found odd number!");
1460
1490
false
@@ -1471,7 +1501,7 @@ to the next iteration, write `again`.
1471
1501
~~~~
1472
1502
# use each = vec::each;
1473
1503
# use println = io::println;
1474
- for each(~ [2, 4, 8, 5, 16]) |n| {
1504
+ for each(& [2, 4, 8, 5, 16]) |n| {
1475
1505
if *n % 2 != 0 {
1476
1506
println(~"found odd number!");
1477
1507
break;
@@ -1486,7 +1516,7 @@ function, not just the loop body.
1486
1516
1487
1517
~~~~
1488
1518
# use each = vec::each;
1489
- fn contains(v: ~ [int], elt: int) -> bool {
1519
+ fn contains(v: & [int], elt: int) -> bool {
1490
1520
for each(v) |x| {
1491
1521
if (*x == elt) { return true; }
1492
1522
}
0 commit comments