@@ -896,6 +896,8 @@ Rust types with the `impl` keyword. As an example, lets define a draw
896
896
method on our ` Shape ` enum.
897
897
898
898
~~~
899
+ # fn draw_circle(p: Point, f: float) { }
900
+ # fn draw_rectangle(p: Point, p: Point) { }
899
901
struct Point {
900
902
x: float,
901
903
y: float
@@ -915,17 +917,18 @@ impl Shape {
915
917
}
916
918
}
917
919
918
- let s = Circle(Point { x: 1f, y: 2f }, 3f } ;
920
+ let s = Circle(Point { x: 1f, y: 2f }, 3f) ;
919
921
s.draw();
920
922
~~~
921
923
922
924
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 ) .
929
932
930
933
> *** Note:*** The method definition syntax will change to require
931
934
> declaring the self type explicitly, as the first argument.
@@ -1042,9 +1045,11 @@ during assignment, only copies a pointer, never the contents of the
1042
1045
box.
1043
1046
1044
1047
~~~~
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.
1048
1053
~~~~
1049
1054
1050
1055
Managed boxes never cross task boundaries.
@@ -1059,7 +1064,7 @@ In contrast to maneged boxes, owned boxes have a single owning memory
1059
1064
slot and thus two owned boxes may not refer to the same memory. All
1060
1065
owned boxes across all tasks are allocated on a single _ exchange
1061
1066
heap_ , where their uniquely owned nature allows them to be passed
1062
- between tasks.
1067
+ between tasks efficiently .
1063
1068
1064
1069
Because owned boxes are uniquely owned, copying them involves allocating
1065
1070
a new owned box and duplicating the contents. Copying owned boxes
@@ -1089,16 +1094,16 @@ let x = ~10;
1089
1094
let y = move x;
1090
1095
~~~~
1091
1096
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
-
1097
1097
Owned boxes, when they do not contain any managed boxes, can be sent
1098
1098
to other tasks. The sending task will give up ownership of the box,
1099
1099
and won't be able to access it afterwards. The receiving task will
1100
1100
become the sole owner of the box.
1101
1101
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
+
1102
1107
## Borrowed pointers
1103
1108
1104
1109
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
1108
1113
imply ownership. Pointers may be borrowed from any type, in which case
1109
1114
the pointer is guaranteed not to outlive the value it points to.
1110
1115
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 ` :
1120
1117
1121
- ~~~~ {.ignore}
1122
- let foo_ptr;
1123
- {
1124
- let foo = ~"foo";
1125
- foo_ptr = &foo;
1118
+ ~~~
1119
+ struct Point {
1120
+ x: float, y: float
1126
1121
}
1127
1122
~~~~
1128
1123
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:
1134
1127
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
+ ~~~
1136
1134
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:
1140
1146
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)
1144
1154
}
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
1146
1195
1147
1196
# Vectors and strings
1148
1197
@@ -1719,8 +1768,8 @@ impl ~str: Printable {
1719
1768
# (~"foo").print();
1720
1769
~~~~
1721
1770
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
1724
1773
static overloading—when the Rust compiler sees the `print` method
1725
1774
call, it looks for an implementation that matches the type with a
1726
1775
method that matches the name, and simply calls that.
0 commit comments