Skip to content

Commit c94d2e3

Browse files
author
blake2-ppc
committed
---
yaml --- r: 81258 b: refs/heads/snap-stage3 c: 8163cb5 h: refs/heads/master v: v3
1 parent 9f53faa commit c94d2e3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+580
-503
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 4c6bf4872012c010f84dc7fa2cdfe87522533f89
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 5011bbfbb69fd92a2b2d973a1cab1613a567afc6
4+
refs/heads/snap-stage3: 8163cb53903dd09e920b6267eba72793394b77d0
55
refs/heads/try: 70152ff55722878cde684ee6462c14c65f2c4729
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/doc/tutorial.md

Lines changed: 58 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -923,60 +923,22 @@ custom destructors.
923923

924924
# Boxes
925925

926-
A value in Rust is stored directly inside the owner. If a `struct` contains
927-
four `int` fields, it will be four times as large as a single `int`. The
928-
following `struct` type is invalid, as it would have an infinite size:
926+
Many modern languages represent values as pointers to heap memory by
927+
default. In contrast, Rust, like C and C++, represents such types directly.
928+
Another way to say this is that aggregate data in Rust are *unboxed*. This
929+
means that if you `let x = Point { x: 1f, y: 1f };`, you are creating a struct
930+
on the stack. If you then copy it into a data structure, you copy the entire
931+
struct, not just a pointer.
929932

930-
~~~~ {.xfail-test}
931-
struct List {
932-
next: Option<List>,
933-
data: int
934-
}
935-
~~~~
936-
937-
> ***Note:*** The `Option` type is an enum representing an *optional* value.
938-
> It's comparable to a nullable pointer in many other languages, but stores the
939-
> contained value unboxed.
940-
941-
An *owned box* (`~`) uses a heap allocation to provide the invariant of always
942-
being the size of a pointer, regardless of the contained type. This can be
943-
leveraged to create a valid recursive `struct` type with a finite size:
944-
945-
~~~~
946-
struct List {
947-
next: Option<~List>,
948-
data: int
949-
}
950-
~~~~
951-
952-
Since an owned box has a single owner, they are limited to representing
953-
tree-like data structures.
954-
955-
The most common use case for owned boxes is creating recursive data structures
956-
like a binary search tree. Rust's trait-based generics system (covered later in
957-
the tutorial) is usually used for static dispatch, but also provides dynamic
958-
dispatch via boxing. Values of different types may have different sizes, but a
959-
box is able to *erase* the difference via the layer of indirection they
960-
provide.
933+
For small structs like `Point`, this is usually more efficient than allocating
934+
memory and indirecting through a pointer. But for big structs, or mutable
935+
state, it can be useful to have a single copy on the stack or on the heap, and
936+
refer to that through a pointer.
961937

962-
In uncommon cases, the indirection can provide a performance gain or memory
963-
reduction by making values smaller. However, unboxed values should almost
964-
always be preferred.
938+
## Owned boxes
965939

966-
Note that returning large unboxed values via boxes is unnecessary. A large
967-
value is returned via a hidden output parameter, and the decision on where to
968-
place the return value should be left to the caller:
969-
970-
~~~~
971-
fn foo() -> (int, int, int, int, int, int) {
972-
(5, 5, 5, 5, 5, 5)
973-
}
974-
975-
let x = ~foo(); // allocates, and writes the integers directly to it
976-
~~~~
977-
978-
Beyond the properties granted by the size, an owned box behaves as a regular
979-
value by inheriting the mutability and lifetime of the owner:
940+
An owned box (`~`) is a uniquely owned allocation on the heap. It inherits the
941+
mutability and lifetime of the owner as it would if there was no box:
980942

981943
~~~~
982944
let x = 5; // immutable
@@ -988,33 +950,35 @@ let mut y = ~5; // mutable
988950
*y += 2; // the * operator is needed to access the contained value
989951
~~~~
990952

991-
As covered earlier, an owned box has a destructor to clean up the allocated
992-
memory. This makes it more restricted than an unboxed type with no destructor
993-
by introducing *move semantics*.
953+
The purpose of an owned box is to add a layer of indirection in order to create
954+
recursive data structures or cheaply pass around an object larger than a
955+
pointer. Since an owned box has a unique owner, it can only be used to
956+
represent a tree data structure.
994957

995-
# Move semantics
958+
The following struct won't compile, because the lack of indirection would mean
959+
it has an infinite size:
996960

997-
Rust uses a shallow copy for parameter passing, assignment and returning from
998-
functions. This is considered a move of ownership for types with destructors.
999-
After a value has been moved, it can no longer be used from the source location
1000-
and will not be destroyed when the source goes out of scope.
1001-
1002-
~~~~
1003-
let x = ~5;
1004-
let y = x.clone(); // y is a newly allocated box
1005-
let z = x; // no new memory allocated, x can no longer be used
961+
~~~~ {.xfail-test}
962+
struct Foo {
963+
child: Option<Foo>
964+
}
1006965
~~~~
1007966

1008-
The mutability of a value may be changed by moving it to a new owner:
967+
> ***Note:*** The `Option` type is an enum that represents an *optional* value.
968+
> It's comparable to a nullable pointer in many other languages, but stores the
969+
> contained value unboxed.
970+
971+
Adding indirection with an owned pointer allocates the child outside of the
972+
struct on the heap, which makes it a finite size and won't result in a
973+
compile-time error:
1009974

1010975
~~~~
1011-
let r = ~13;
1012-
let mut s = r; // box becomes mutable
1013-
*s += 1;
1014-
let t = s; // box becomes immutable
976+
struct Foo {
977+
child: Option<~Foo>
978+
}
1015979
~~~~
1016980

1017-
# Managed boxes
981+
## Managed boxes
1018982

1019983
A managed box (`@`) is a heap allocation with the lifetime managed by a
1020984
task-local garbage collector. It will be destroyed at some point after there
@@ -1059,6 +1023,30 @@ d = b; // box type is the same, okay
10591023
c = b; // error
10601024
~~~~
10611025

1026+
# Move semantics
1027+
1028+
Rust uses a shallow copy for parameter passing, assignment and returning values
1029+
from functions. A shallow copy is considered a move of ownership if the
1030+
ownership tree of the copied value includes an owned box or a type with a
1031+
custom destructor. After a value has been moved, it can no longer be used from
1032+
the source location and will not be destroyed there.
1033+
1034+
~~~~
1035+
let x = ~5;
1036+
let y = x.clone(); // y is a newly allocated box
1037+
let z = x; // no new memory allocated, x can no longer be used
1038+
~~~~
1039+
1040+
Since in owned boxes mutability is a property of the owner, not the
1041+
box, mutable boxes may become immutable when they are moved, and vice-versa.
1042+
1043+
~~~~
1044+
let r = ~13;
1045+
let mut s = r; // box becomes mutable
1046+
*s += 1;
1047+
let t = s; // box becomes immutable
1048+
~~~~
1049+
10621050
# Borrowed pointers
10631051

10641052
Rust's borrowed pointers are a general purpose reference type. In contrast with

0 commit comments

Comments
 (0)