Skip to content

Commit 54483ab

Browse files
committed
---
yaml --- r: 24125 b: refs/heads/master c: 91fe3fc h: refs/heads/master i: 24123: d72d1ee v: v3
1 parent d228e22 commit 54483ab

File tree

2 files changed

+95
-46
lines changed

2 files changed

+95
-46
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: b3c72713def77769107488d91f600f805bd68419
2+
refs/heads/master: 91fe3fcbef43c68943b57b0cfaf637c84d39926c
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: cd6f24f9d14ac90d167386a56e7a6ac1f0318195
55
refs/heads/try: ffbe0e0e00374358b789b0037bcb3a577cd218be

trunk/doc/tutorial.md

Lines changed: 94 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,8 @@ Rust types with the `impl` keyword. As an example, lets define a draw
896896
method on our `Shape` enum.
897897

898898
~~~
899+
# fn draw_circle(p: Point, f: float) { }
900+
# fn draw_rectangle(p: Point, p: Point) { }
899901
struct Point {
900902
x: float,
901903
y: float
@@ -915,17 +917,18 @@ impl Shape {
915917
}
916918
}
917919
918-
let s = Circle(Point { x: 1f, y: 2f }, 3f };
920+
let s = Circle(Point { x: 1f, y: 2f }, 3f);
919921
s.draw();
920922
~~~
921923

922924
This defines an _implementation_ for `Shape` containing a single
923-
method, `draw`. If we wanted we could add additional methods to the
924-
same impl. In most most respects the `draw` method is defined like
925-
any other function, with the exception of the name `self`. `self` is a
926-
special value that is automatically defined in each method, referring
927-
to the value being operated on. We'll discuss methods more in the
928-
context of [traits and generics](#generics).
925+
method, `draw`. In most most respects the `draw` method is defined
926+
like any other function, with the exception of the name `self`. `self`
927+
is a special value that is automatically defined in each method,
928+
referring to the value being operated on. If we wanted we could add
929+
additional methods to the same impl, or multiple impls for the same
930+
type. We'll discuss methods more in the context of [traits and
931+
generics](#generics).
929932

930933
> ***Note:*** The method definition syntax will change to require
931934
> declaring the self type explicitly, as the first argument.
@@ -1042,9 +1045,11 @@ during assignment, only copies a pointer, never the contents of the
10421045
box.
10431046

10441047
~~~~
1045-
let x: @int = @10; // New box, refcount of 1
1046-
let y = x; // Copy the pointer, increase refcount
1047-
// When x and y go out of scope, refcount goes to 0, box is freed
1048+
let x: @int = @10; // New box
1049+
let y = x; // Copy of a pointer to the same box
1050+
1051+
// x and y both refer to the same allocation. When both go out of scope
1052+
// then the allocation will be freed.
10481053
~~~~
10491054

10501055
Managed boxes never cross task boundaries.
@@ -1059,7 +1064,7 @@ In contrast to maneged boxes, owned boxes have a single owning memory
10591064
slot and thus two owned boxes may not refer to the same memory. All
10601065
owned boxes across all tasks are allocated on a single _exchange
10611066
heap_, where their uniquely owned nature allows them to be passed
1062-
between tasks.
1067+
between tasks efficiently.
10631068

10641069
Because owned boxes are uniquely owned, copying them involves allocating
10651070
a new owned box and duplicating the contents. Copying owned boxes
@@ -1089,16 +1094,16 @@ let x = ~10;
10891094
let y = move x;
10901095
~~~~
10911096

1092-
> ***Note:*** this discussion of copying vs moving does not account
1093-
> for the "last use" rules that automatically promote copy operations
1094-
> to moves. This is an evolving area of the language that will
1095-
> continue to change.
1096-
10971097
Owned boxes, when they do not contain any managed boxes, can be sent
10981098
to other tasks. The sending task will give up ownership of the box,
10991099
and won't be able to access it afterwards. The receiving task will
11001100
become the sole owner of the box.
11011101

1102+
> ***Note:*** this discussion of copying vs moving does not account
1103+
> for the "last use" rules that automatically promote copy operations
1104+
> to moves. Last use is expected to be removed from the language in
1105+
> favor of explicit moves.
1106+
11021107
## Borrowed pointers
11031108

11041109
Rust borrowed pointers are a general purpose reference/pointer type,
@@ -1108,41 +1113,85 @@ pointer is the owner of the pointed-to memory, borrowed pointers never
11081113
imply ownership. Pointers may be borrowed from any type, in which case
11091114
the pointer is guaranteed not to outlive the value it points to.
11101115

1111-
~~~~
1112-
# fn work_with_foo_by_pointer(f: &~str) { }
1113-
let foo = ~"foo";
1114-
work_with_foo_by_pointer(&foo);
1115-
~~~~
1116-
1117-
The following shows an example of what is _not_ possible with borrowed
1118-
pointers. If you were able to write this then the pointer to `foo`
1119-
would outlive `foo` itself.
1116+
As an example, consider a simple struct type, `Point`:
11201117

1121-
~~~~ {.ignore}
1122-
let foo_ptr;
1123-
{
1124-
let foo = ~"foo";
1125-
foo_ptr = &foo;
1118+
~~~
1119+
struct Point {
1120+
x: float, y: float
11261121
}
11271122
~~~~
11281123
1129-
> ***Note:*** borrowed pointers are a new addition to the language.
1130-
> They are not used extensively yet but are expected to become the
1131-
> pointer type used in many common situations, in particular for
1132-
> by-reference argument passing. Rust's current solution for passing
1133-
> arguments by reference is [argument modes](#argument-passing).
1124+
We can use this simple definition to allocate points in many ways. For
1125+
example, in this code, each of these three local variables contains a
1126+
point, but allocated in a different place:
11341127
1135-
## Mutability
1128+
~~~
1129+
# struct Point { x: float, y: float }
1130+
let on_the_stack : Point = Point {x: 3.0, y: 4.0};
1131+
let shared_box : @Point = @Point {x: 5.0, y: 1.0};
1132+
let unique_box : ~Point = ~Point {x: 7.0, y: 9.0};
1133+
~~~
11361134
1137-
All pointer types have a mutable variant, written `@mut T` or `~mut
1138-
T`. Given such a pointer, you can write to its contents by combining
1139-
the dereference operator with a mutating action.
1135+
Suppose we wanted to write a procedure that computed the distance
1136+
between any two points, no matter where they were stored. For example,
1137+
we might like to compute the distance between `on_the_stack` and
1138+
`shared_box`, or between `shared_box` and `unique_box`. One option is
1139+
to define a function that takes two arguments of type point—that is,
1140+
it takes the points by value. But this will cause the points to be
1141+
copied when we call the function. For points, this is probably not so
1142+
bad, but often copies are expensive or, worse, if there are mutable
1143+
fields, they can change the semantics of your program. So we’d like to
1144+
define a function that takes the points by pointer. We can use
1145+
borrowed pointers to do this:
11401146
1141-
~~~~
1142-
fn increase_contents(pt: @mut int) {
1143-
*pt += 1;
1147+
~~~
1148+
# struct Point { x: float, y: float }
1149+
# fn sqrt(f: float) -> float { 0f }
1150+
fn compute_distance(p1: &Point, p2: &Point) -> float {
1151+
let x_d = p1.x - p2.x;
1152+
let y_d = p1.y - p2.y;
1153+
sqrt(x_d * x_d + y_d * y_d)
11441154
}
1145-
~~~~
1155+
~~~
1156+
1157+
Now we can call `compute_distance()` in various ways:
1158+
1159+
~~~
1160+
# struct Point{ x: float, y: float };
1161+
# let on_the_stack : Point = Point {x: 3.0, y: 4.0};
1162+
# let shared_box : @Point = @Point {x: 5.0, y: 1.0};
1163+
# let unique_box : ~Point = ~Point {x: 7.0, y: 9.0};
1164+
# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }
1165+
compute_distance(&on_the_stack, shared_box);
1166+
compute_distance(shared_box, unique_box);
1167+
~~~
1168+
1169+
Here the `&` operator is used to take the address of the variable
1170+
`on_the_stack`; this is because `on_the_stack` has the type `point`
1171+
(that is, a record value) and we have to take its address to get a
1172+
value. We also call this _borrowing_ the local variable
1173+
`on_the_stack`, because we are created an alias: that is, another
1174+
route to the same data.
1175+
1176+
In the case of the boxes `shared_box` and `unique_box`, however, no
1177+
explicit action is necessary. The compiler will automatically convert
1178+
a box like `@point` or `~point` to a borrowed pointer like
1179+
`&point`. This is another form of borrowing; in this case, the
1180+
contents of the shared/unique box is being lent out.
1181+
1182+
Whenever a value is borrowed, there are some limitations on what you
1183+
can do with the original. For example, if the contents of a variable
1184+
have been lent out, you cannot send that variable to another task, nor
1185+
will you be permitted to take actions that might cause the borrowed
1186+
value to be freed or to change its type. This rule should make
1187+
intuitive sense: you must wait for a borrowed value to be returned
1188+
(that is, for the borrowed pointer to go out of scope) before you can
1189+
make full use of it again.
1190+
1191+
For a more in-depth explanation of borrowed pointers, read the
1192+
[borrowed pointer tutorial][borrowtut].
1193+
1194+
[borrowtut]: tutorial-borrowed-ptr.html
11461195
11471196
# Vectors and strings
11481197
@@ -1719,8 +1768,8 @@ impl ~str: Printable {
17191768
# (~"foo").print();
17201769
~~~~
17211770
1722-
Given these, we may call `1.to_str()` to print `"1"`, or
1723-
`(~"foo").to_str()` to print `"foo"` again. This is basically a form of
1771+
Given these, we may call `1.print()` to print `"1"`, or
1772+
`(~"foo").print()` to print `"foo"` again, as with . This is basically a form of
17241773
static overloading—when the Rust compiler sees the `print` method
17251774
call, it looks for an implementation that matches the type with a
17261775
method that matches the name, and simply calls that.

0 commit comments

Comments
 (0)