]> git.lizzy.rs Git - rust.git/blob - doc/po/tutorial-borrowed-ptr.md.pot
Update version numbers to 0.8
[rust.git] / doc / po / tutorial-borrowed-ptr.md.pot
1 # SOME DESCRIPTIVE TITLE
2 # Copyright (C) YEAR The Rust Project Developers
3 # This file is distributed under the same license as the Rust package.
4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5 #
6 #, fuzzy
7 msgid ""
8 msgstr ""
9 "Project-Id-Version: Rust 0.8\n"
10 "POT-Creation-Date: 2013-07-22 23:37+0900\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
14 "Language: \n"
15 "MIME-Version: 1.0\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
17 "Content-Transfer-Encoding: 8bit\n"
18
19 #. type: Plain text
20 #: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
21 #: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
22 #: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
23 msgid "# Introduction"
24 msgstr ""
25
26 #. type: Plain text
27 #: doc/tutorial.md:1108 doc/tutorial-borrowed-ptr.md:72
28 msgid "Now we can call `compute_distance()` in various ways:"
29 msgstr ""
30
31 #. type: Plain text
32 #: doc/tutorial-borrowed-ptr.md:2
33 msgid "% Rust Borrowed Pointers Tutorial"
34 msgstr ""
35
36 #. type: Plain text
37 #: doc/tutorial-borrowed-ptr.md:14
38 msgid ""
39 "Borrowed pointers are one of the more flexible and powerful tools available "
40 "in Rust. A borrowed pointer can point anywhere: into the managed or exchange "
41 "heap, into the stack, and even into the interior of another data structure. "
42 "A borrowed pointer is as flexible as a C pointer or C++ reference. However, "
43 "unlike C and C++ compilers, the Rust compiler includes special static checks "
44 "that ensure that programs use borrowed pointers safely. Another advantage of "
45 "borrowed pointers is that they are invisible to the garbage collector, so "
46 "working with borrowed pointers helps reduce the overhead of automatic memory "
47 "management."
48 msgstr ""
49
50 #. type: Plain text
51 #: doc/tutorial-borrowed-ptr.md:18
52 msgid ""
53 "Despite their complete safety, a borrowed pointer's representation at "
54 "runtime is the same as that of an ordinary pointer in a C program. They "
55 "introduce zero overhead. The compiler does all safety checks at compile time."
56 msgstr ""
57
58 #. type: Plain text
59 #: doc/tutorial-borrowed-ptr.md:24
60 msgid ""
61 "Although borrowed pointers have rather elaborate theoretical underpinnings "
62 "(region pointers), the core concepts will be familiar to anyone who has "
63 "worked with C or C++. Therefore, the best way to explain how they are used—"
64 "and their limitations—is probably just to work through several examples."
65 msgstr ""
66
67 #. type: Plain text
68 #: doc/tutorial-borrowed-ptr.md:26
69 msgid "# By example"
70 msgstr ""
71
72 #. type: Plain text
73 #: doc/tutorial-borrowed-ptr.md:31
74 msgid ""
75 "Borrowed pointers are called *borrowed* because they are only valid for a "
76 "limited duration. Borrowed pointers never claim any kind of ownership over "
77 "the data that they point to: instead, they are used for cases where you "
78 "would like to use data for a short time."
79 msgstr ""
80
81 #. type: Plain text
82 #: doc/tutorial-borrowed-ptr.md:33
83 msgid "As an example, consider a simple struct type `Point`:"
84 msgstr ""
85
86 #. type: Plain text
87 #: doc/tutorial-borrowed-ptr.md:37
88 msgid "~~~ struct Point {x: float, y: float} ~~~"
89 msgstr ""
90
91 #. type: Plain text
92 #: doc/tutorial-borrowed-ptr.md:41
93 msgid ""
94 "We can use this simple definition to allocate points in many different ways. "
95 "For example, in this code, each of these three local variables contains a "
96 "point, but allocated in a different place:"
97 msgstr ""
98
99 #. type: Plain text
100 #: doc/tutorial-borrowed-ptr.md:48
101 #, no-wrap
102 msgid ""
103 "~~~\n"
104 "# struct Point {x: float, y: float}\n"
105 "let on_the_stack :  Point =  Point {x: 3.0, y: 4.0};\n"
106 "let managed_box  : @Point = @Point {x: 5.0, y: 1.0};\n"
107 "let owned_box    : ~Point = ~Point {x: 7.0, y: 9.0};\n"
108 "~~~\n"
109 msgstr ""
110
111 #. type: Plain text
112 #: doc/tutorial-borrowed-ptr.md:60
113 msgid ""
114 "Suppose we wanted to write a procedure that computed the distance between "
115 "any two points, no matter where they were stored. For example, we might like "
116 "to compute the distance between `on_the_stack` and `managed_box`, or between "
117 "`managed_box` and `owned_box`. One option is to define a function that takes "
118 "two arguments of type `Point`—that is, it takes the points by value. But if "
119 "we define it this way, calling the function will cause the points to be "
120 "copied. For points, this is probably not so bad, but often copies are "
121 "expensive. Worse, if the data type contains mutable fields, copying can "
122 "change the semantics of your program in unexpected ways. So we'd like to "
123 "define a function that takes the points by pointer. We can use borrowed "
124 "pointers to do this:"
125 msgstr ""
126
127 #. type: Plain text
128 #: doc/tutorial-borrowed-ptr.md:70
129 #, no-wrap
130 msgid ""
131 "~~~\n"
132 "# struct Point {x: float, y: float}\n"
133 "# fn sqrt(f: float) -> float { 0f }\n"
134 "fn compute_distance(p1: &Point, p2: &Point) -> float {\n"
135 "    let x_d = p1.x - p2.x;\n"
136 "    let y_d = p1.y - p2.y;\n"
137 "    sqrt(x_d * x_d + y_d * y_d)\n"
138 "}\n"
139 "~~~\n"
140 msgstr ""
141
142 #. type: Plain text
143 #: doc/tutorial-borrowed-ptr.md:82
144 #, no-wrap
145 msgid ""
146 "~~~\n"
147 "# struct Point {x: float, y: float}\n"
148 "# let on_the_stack :  Point =  Point{x: 3.0, y: 4.0};\n"
149 "# let managed_box  : @Point = @Point{x: 5.0, y: 1.0};\n"
150 "# let owned_box    : ~Point = ~Point{x: 7.0, y: 9.0};\n"
151 "# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }\n"
152 "compute_distance(&on_the_stack, managed_box);\n"
153 "compute_distance(managed_box, owned_box);\n"
154 "~~~\n"
155 msgstr ""
156
157 #. type: Plain text
158 #: doc/tutorial-borrowed-ptr.md:89
159 msgid ""
160 "Here, the `&` operator takes the address of the variable `on_the_stack`; "
161 "this is because `on_the_stack` has the type `Point` (that is, a struct "
162 "value) and we have to take its address to get a value. We also call this "
163 "_borrowing_ the local variable `on_the_stack`, because we have created an "
164 "alias: that is, another name for the same data."
165 msgstr ""
166
167 #. type: Plain text
168 #: doc/tutorial-borrowed-ptr.md:95
169 msgid ""
170 "In contrast, we can pass the boxes `managed_box` and `owned_box` to "
171 "`compute_distance` directly. The compiler automatically converts a box like "
172 "`@Point` or `~Point` to a borrowed pointer like `&Point`. This is another "
173 "form of borrowing: in this case, the caller lends the contents of the "
174 "managed or owned box to the callee."
175 msgstr ""
176
177 #. type: Plain text
178 #: doc/tutorial-borrowed-ptr.md:105
179 msgid ""
180 "Whenever a caller lends data to a callee, there are some limitations on what "
181 "the caller can do with the original. For example, if the contents of a "
182 "variable have been lent out, you cannot send that variable to another task. "
183 "In addition, the compiler will reject any code that might cause the borrowed "
184 "value to be freed or overwrite its component fields with values of different "
185 "types (I'll get into what kinds of actions those are shortly). This rule "
186 "should make intuitive sense: you must wait for a borrower to return the "
187 "value that you lent it (that is, wait for the borrowed pointer to go out of "
188 "scope)  before you can make full use of it again."
189 msgstr ""
190
191 #. type: Plain text
192 #: doc/tutorial-borrowed-ptr.md:107
193 msgid "# Other uses for the & operator"
194 msgstr ""
195
196 #. type: Plain text
197 #: doc/tutorial-borrowed-ptr.md:109
198 msgid "In the previous example, the value `on_the_stack` was defined like so:"
199 msgstr ""
200
201 #. type: Plain text
202 #: doc/tutorial-borrowed-ptr.md:114
203 msgid ""
204 "~~~ # struct Point {x: float, y: float} let on_the_stack: Point = Point {x: "
205 "3.0, y: 4.0}; ~~~"
206 msgstr ""
207
208 #. type: Plain text
209 #: doc/tutorial-borrowed-ptr.md:119
210 msgid ""
211 "This declaration means that code can only pass `Point` by value to other "
212 "functions. As a consequence, we had to explicitly take the address of "
213 "`on_the_stack` to get a borrowed pointer. Sometimes however it is more "
214 "convenient to move the & operator into the definition of `on_the_stack`:"
215 msgstr ""
216
217 #. type: Plain text
218 #: doc/tutorial-borrowed-ptr.md:124
219 msgid ""
220 "~~~ # struct Point {x: float, y: float} let on_the_stack2: &Point = &Point "
221 "{x: 3.0, y: 4.0}; ~~~"
222 msgstr ""
223
224 #. type: Plain text
225 #: doc/tutorial-borrowed-ptr.md:128
226 msgid ""
227 "Applying `&` to an rvalue (non-assignable location) is just a convenient "
228 "shorthand for creating a temporary and taking its address. A more verbose "
229 "way to write the same code is:"
230 msgstr ""
231
232 #. type: Plain text
233 #: doc/tutorial-borrowed-ptr.md:134
234 msgid ""
235 "~~~ # struct Point {x: float, y: float} let tmp = Point {x: 3.0, y: 4.0}; "
236 "let on_the_stack2 : &Point = &tmp; ~~~"
237 msgstr ""
238
239 #. type: Plain text
240 #: doc/tutorial-borrowed-ptr.md:136
241 msgid "# Taking the address of fields"
242 msgstr ""
243
244 #. type: Plain text
245 #: doc/tutorial-borrowed-ptr.md:141
246 msgid ""
247 "As in C, the `&` operator is not limited to taking the address of local "
248 "variables. It can also take the address of fields or individual array "
249 "elements. For example, consider this type definition for `rectangle`:"
250 msgstr ""
251
252 #. type: Plain text
253 #: doc/tutorial-borrowed-ptr.md:147
254 msgid ""
255 "~~~ struct Point {x: float, y: float} // as before struct Size {w: float, h: "
256 "float} // as before struct Rectangle {origin: Point, size: Size} ~~~"
257 msgstr ""
258
259 #. type: Plain text
260 #: doc/tutorial-borrowed-ptr.md:149
261 msgid "Now, as before, we can define rectangles in a few different ways:"
262 msgstr ""
263
264 #. type: Plain text
265 #: doc/tutorial-borrowed-ptr.md:161
266 #, no-wrap
267 msgid ""
268 "~~~\n"
269 "# struct Point {x: float, y: float}\n"
270 "# struct Size {w: float, h: float} // as before\n"
271 "# struct Rectangle {origin: Point, size: Size}\n"
272 "let rect_stack   = &Rectangle {origin: Point {x: 1f, y: 2f},\n"
273 "                               size: Size {w: 3f, h: 4f}};\n"
274 "let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f},\n"
275 "                               size: Size {w: 3f, h: 4f}};\n"
276 "let rect_owned   = ~Rectangle {origin: Point {x: 5f, y: 6f},\n"
277 "                               size: Size {w: 3f, h: 4f}};\n"
278 "~~~\n"
279 msgstr ""
280
281 #. type: Plain text
282 #: doc/tutorial-borrowed-ptr.md:164
283 msgid ""
284 "In each case, we can extract out individual subcomponents with the `&` "
285 "operator. For example, I could write:"
286 msgstr ""
287
288 #. type: Plain text
289 #: doc/tutorial-borrowed-ptr.md:175
290 msgid ""
291 "~~~ # struct Point {x: float, y: float} // as before # struct Size {w: "
292 "float, h: float} // as before # struct Rectangle {origin: Point, size: Size} "
293 "# let rect_stack = &Rectangle {origin: Point {x: 1f, y: 2f}, size: Size {w: "
294 "3f, h: 4f}}; # let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f}, "
295 "size: Size {w: 3f, h: 4f}}; # let rect_owned = ~Rectangle {origin: Point {x: "
296 "5f, y: 6f}, size: Size {w: 3f, h: 4f}}; # fn compute_distance(p1: &Point, "
297 "p2: &Point) -> float { 0f } compute_distance(&rect_stack.origin, "
298 "&rect_managed.origin); ~~~"
299 msgstr ""
300
301 #. type: Plain text
302 #: doc/tutorial-borrowed-ptr.md:178
303 msgid ""
304 "which would borrow the field `origin` from the rectangle on the stack as "
305 "well as from the managed box, and then compute the distance between them."
306 msgstr ""
307
308 #. type: Plain text
309 #: doc/tutorial-borrowed-ptr.md:180
310 msgid "# Borrowing managed boxes and rooting"
311 msgstr ""
312
313 #. type: Plain text
314 #: doc/tutorial-borrowed-ptr.md:186
315 msgid ""
316 "We’ve seen a few examples so far of borrowing heap boxes, both managed and "
317 "owned. Up till this point, we’ve glossed over issues of safety. As stated in "
318 "the introduction, at runtime a borrowed pointer is simply a pointer, nothing "
319 "more. Therefore, avoiding C's problems with dangling pointers requires a "
320 "compile-time safety check."
321 msgstr ""
322
323 #. type: Plain text
324 #: doc/tutorial-borrowed-ptr.md:197
325 msgid ""
326 "The basis for the check is the notion of _lifetimes_. A lifetime is a static "
327 "approximation of the span of execution during which the pointer is valid: it "
328 "always corresponds to some expression or block within the program. Code "
329 "inside that expression can use the pointer without restrictions. But if the "
330 "pointer escapes from that expression (for example, if the expression "
331 "contains an assignment expression that assigns the pointer to a mutable "
332 "field of a data structure with a broader scope than the pointer itself), the "
333 "compiler reports an error. We'll be discussing lifetimes more in the "
334 "examples to come, and a more thorough introduction is also available."
335 msgstr ""
336
337 #. type: Plain text
338 #: doc/tutorial-borrowed-ptr.md:202
339 msgid ""
340 "When the `&` operator creates a borrowed pointer, the compiler must ensure "
341 "that the pointer remains valid for its entire lifetime. Sometimes this is "
342 "relatively easy, such as when taking the address of a local variable or a "
343 "field that is stored on the stack:"
344 msgstr ""
345
346 #. type: Plain text
347 #: doc/tutorial-borrowed-ptr.md:211
348 #, no-wrap
349 msgid ""
350 "~~~\n"
351 "struct X { f: int }\n"
352 "fn example1() {\n"
353 "    let mut x = X { f: 3 };\n"
354 "    let y = &mut x.f;  // -+ L\n"
355 "    ...                //  |\n"
356 "}                      // -+\n"
357 "~~~\n"
358 msgstr ""
359
360 #. type: Plain text
361 #: doc/tutorial-borrowed-ptr.md:216
362 msgid ""
363 "Here, the lifetime of the borrowed pointer `y` is simply L, the remainder of "
364 "the function body. The compiler need not do any other work to prove that "
365 "code will not free `x.f`. This is true even if the code mutates `x`."
366 msgstr ""
367
368 #. type: Plain text
369 #: doc/tutorial-borrowed-ptr.md:218
370 msgid "The situation gets more complex when borrowing data inside heap boxes:"
371 msgstr ""
372
373 #. type: Plain text
374 #: doc/tutorial-borrowed-ptr.md:227
375 #, no-wrap
376 msgid ""
377 "~~~\n"
378 "# struct X { f: int }\n"
379 "fn example2() {\n"
380 "    let mut x = @X { f: 3 };\n"
381 "    let y = &x.f;      // -+ L\n"
382 "    ...                //  |\n"
383 "}                      // -+\n"
384 "~~~\n"
385 msgstr ""
386
387 #. type: Plain text
388 #: doc/tutorial-borrowed-ptr.md:238
389 msgid ""
390 "In this example, the value `x` is a heap box, and `y` is therefore a pointer "
391 "into that heap box. Again the lifetime of `y` is L, the remainder of the "
392 "function body. But there is a crucial difference: suppose `x` were to be "
393 "reassigned during the lifetime L? If the compiler isn't careful, the managed "
394 "box could become *unrooted*, and would therefore be subject to garbage "
395 "collection. A heap box that is unrooted is one such that no pointer values "
396 "in the heap point to it. It would violate memory safety for the box that was "
397 "originally assigned to `x` to be garbage-collected, since a non-heap pointer "
398 "*`y`* still points into it."
399 msgstr ""
400
401 #. type: Plain text
402 #: doc/tutorial-borrowed-ptr.md:241
403 msgid ""
404 "> ***Note:*** Our current implementation implements the garbage collector > "
405 "using reference counting and cycle detection."
406 msgstr ""
407
408 #. type: Plain text
409 #: doc/tutorial-borrowed-ptr.md:247
410 msgid ""
411 "For this reason, whenever an `&` expression borrows the interior of a "
412 "managed box stored in a mutable location, the compiler inserts a temporary "
413 "that ensures that the managed box remains live for the entire lifetime. So, "
414 "the above example would be compiled as if it were written"
415 msgstr ""
416
417 #. type: Plain text
418 #: doc/tutorial-borrowed-ptr.md:257
419 #, no-wrap
420 msgid ""
421 "~~~\n"
422 "# struct X { f: int }\n"
423 "fn example2() {\n"
424 "    let mut x = @X {f: 3};\n"
425 "    let x1 = x;\n"
426 "    let y = &x1.f;     // -+ L\n"
427 "    ...                //  |\n"
428 "}                      // -+\n"
429 "~~~\n"
430 msgstr ""
431
432 #. type: Plain text
433 #: doc/tutorial-borrowed-ptr.md:260
434 msgid ""
435 "Now if `x` is reassigned, the pointer `y` will still remain valid. This "
436 "process is called *rooting*."
437 msgstr ""
438
439 #. type: Plain text
440 #: doc/tutorial-borrowed-ptr.md:262
441 msgid "# Borrowing owned boxes"
442 msgstr ""
443
444 #. type: Plain text
445 #: doc/tutorial-borrowed-ptr.md:268
446 msgid ""
447 "The previous example demonstrated *rooting*, the process by which the "
448 "compiler ensures that managed boxes remain live for the duration of a "
449 "borrow. Unfortunately, rooting does not work for borrows of owned boxes, "
450 "because it is not possible to have two references to a owned box."
451 msgstr ""
452
453 #. type: Plain text
454 #: doc/tutorial-borrowed-ptr.md:274
455 msgid ""
456 "For owned boxes, therefore, the compiler will only allow a borrow *if the "
457 "compiler can guarantee that the owned box will not be reassigned or moved "
458 "for the lifetime of the pointer*. This does not necessarily mean that the "
459 "owned box is stored in immutable memory. For example, the following function "
460 "is legal:"
461 msgstr ""
462
463 #. type: Plain text
464 #: doc/tutorial-borrowed-ptr.md:289
465 #, no-wrap
466 msgid ""
467 "~~~\n"
468 "# fn some_condition() -> bool { true }\n"
469 "# struct Foo { f: int }\n"
470 "fn example3() -> int {\n"
471 "    let mut x = ~Foo {f: 3};\n"
472 "    if some_condition() {\n"
473 "        let y = &x.f;      // -+ L\n"
474 "        return *y;         //  |\n"
475 "    }                      // -+\n"
476 "    x = ~Foo {f: 4};\n"
477 "    ...\n"
478 "# return 0;\n"
479 "}\n"
480 "~~~\n"
481 msgstr ""
482
483 #. type: Plain text
484 #: doc/tutorial-borrowed-ptr.md:295
485 msgid ""
486 "Here, as before, the interior of the variable `x` is being borrowed and `x` "
487 "is declared as mutable. However, the compiler can prove that `x` is not "
488 "assigned anywhere in the lifetime L of the variable `y`. Therefore, it "
489 "accepts the function, even though `x` is mutable and in fact is mutated "
490 "later in the function."
491 msgstr ""
492
493 #. type: Plain text
494 #: doc/tutorial-borrowed-ptr.md:301
495 msgid ""
496 "It may not be clear why we are so concerned about mutating a borrowed "
497 "variable. The reason is that the runtime system frees any owned box _as soon "
498 "as its owning reference changes or goes out of scope_. Therefore, a program "
499 "like this is illegal (and would be rejected by the compiler):"
500 msgstr ""
501
502 #. type: Plain text
503 #: doc/tutorial-borrowed-ptr.md:310
504 #, no-wrap
505 msgid ""
506 "~~~ {.xfail-test}\n"
507 "fn example3() -> int {\n"
508 "    let mut x = ~X {f: 3};\n"
509 "    let y = &x.f;\n"
510 "    x = ~X {f: 4};  // Error reported here.\n"
511 "    *y\n"
512 "}\n"
513 "~~~\n"
514 msgstr ""
515
516 #. type: Plain text
517 #: doc/tutorial-borrowed-ptr.md:313
518 msgid ""
519 "To make this clearer, consider this diagram showing the state of memory "
520 "immediately before the re-assignment of `x`:"
521 msgstr ""
522
523 #. type: Plain text
524 #: doc/tutorial-borrowed-ptr.md:316 doc/tutorial-borrowed-ptr.md:330
525 #, no-wrap
526 msgid ""
527 "~~~ {.notrust}\n"
528 "    Stack               Exchange Heap\n"
529 msgstr ""
530
531 #. type: Plain text
532 #: doc/tutorial-borrowed-ptr.md:325
533 #, no-wrap
534 msgid ""
535 "  x +----------+\n"
536 "    | ~{f:int} | ----+\n"
537 "  y +----------+     |\n"
538 "    | &int     | ----+\n"
539 "    +----------+     |    +---------+\n"
540 "                     +--> |  f: 3   |\n"
541 "                          +---------+\n"
542 "~~~\n"
543 msgstr ""
544
545 #. type: Plain text
546 #: doc/tutorial-borrowed-ptr.md:327
547 msgid "Once the reassignment occurs, the memory will look like this:"
548 msgstr ""
549
550 #. type: Plain text
551 #: doc/tutorial-borrowed-ptr.md:339
552 #, no-wrap
553 msgid ""
554 "  x +----------+          +---------+\n"
555 "    | ~{f:int} | -------> |  f: 4   |\n"
556 "  y +----------+          +---------+\n"
557 "    | &int     | ----+\n"
558 "    +----------+     |    +---------+\n"
559 "                     +--> | (freed) |\n"
560 "                          +---------+\n"
561 "~~~\n"
562 msgstr ""
563
564 #. type: Plain text
565 #: doc/tutorial-borrowed-ptr.md:342
566 msgid ""
567 "Here you can see that the variable `y` still points at the old box, which "
568 "has been freed."
569 msgstr ""
570
571 #. type: Plain text
572 #: doc/tutorial-borrowed-ptr.md:348
573 msgid ""
574 "In fact, the compiler can apply the same kind of reasoning to any memory "
575 "that is _(uniquely) owned by the stack frame_. So we could modify the "
576 "previous example to introduce additional owned pointers and structs, and the "
577 "compiler will still be able to detect possible mutations:"
578 msgstr ""
579
580 #. type: Plain text
581 #: doc/tutorial-borrowed-ptr.md:353
582 #, no-wrap
583 msgid ""
584 "~~~ {.xfail-test}\n"
585 "fn example3() -> int {\n"
586 "    struct R { g: int }\n"
587 "    struct S { f: ~R }\n"
588 msgstr ""
589
590 #. type: Plain text
591 #: doc/tutorial-borrowed-ptr.md:361
592 #, no-wrap
593 msgid ""
594 "    let mut x = ~S {f: ~R {g: 3}};\n"
595 "    let y = &x.f.g;\n"
596 "    x = ~S {f: ~R {g: 4}};  // Error reported here.\n"
597 "    x.f = ~R {g: 5};        // Error reported here.\n"
598 "    *y\n"
599 "}\n"
600 "~~~\n"
601 msgstr ""
602
603 #. type: Plain text
604 #: doc/tutorial-borrowed-ptr.md:365
605 msgid ""
606 "In this case, two errors are reported, one when the variable `x` is modified "
607 "and another when `x.f` is modified. Either modification would invalidate the "
608 "pointer `y`."
609 msgstr ""
610
611 #. type: Plain text
612 #: doc/tutorial-borrowed-ptr.md:367
613 msgid "# Borrowing and enums"
614 msgstr ""
615
616 #. type: Plain text
617 #: doc/tutorial-borrowed-ptr.md:373
618 msgid ""
619 "The previous example showed that the type system forbids any borrowing of "
620 "owned boxes found in aliasable, mutable memory. This restriction prevents "
621 "pointers from pointing into freed memory. There is one other case where the "
622 "compiler must be very careful to ensure that pointers remain valid: pointers "
623 "into the interior of an `enum`."
624 msgstr ""
625
626 #. type: Plain text
627 #: doc/tutorial-borrowed-ptr.md:376
628 msgid ""
629 "As an example, let’s look at the following `shape` type that can represent "
630 "both rectangles and circles:"
631 msgstr ""
632
633 #. type: Plain text
634 #: doc/tutorial-borrowed-ptr.md:385
635 #, no-wrap
636 msgid ""
637 "~~~\n"
638 "struct Point {x: float, y: float}; // as before\n"
639 "struct Size {w: float, h: float}; // as before\n"
640 "enum Shape {\n"
641 "    Circle(Point, float),   // origin, radius\n"
642 "    Rectangle(Point, Size)  // upper-left, dimensions\n"
643 "}\n"
644 "~~~\n"
645 msgstr ""
646
647 #. type: Plain text
648 #: doc/tutorial-borrowed-ptr.md:389
649 msgid ""
650 "Now we might write a function to compute the area of a shape. This function "
651 "takes a borrowed pointer to a shape, to avoid the need for copying."
652 msgstr ""
653
654 #. type: Plain text
655 #: doc/tutorial-borrowed-ptr.md:405
656 #, no-wrap
657 msgid ""
658 "~~~\n"
659 "# struct Point {x: float, y: float}; // as before\n"
660 "# struct Size {w: float, h: float}; // as before\n"
661 "# enum Shape {\n"
662 "#     Circle(Point, float),   // origin, radius\n"
663 "#     Rectangle(Point, Size)  // upper-left, dimensions\n"
664 "# }\n"
665 "# static tau: float = 6.28f;\n"
666 "fn compute_area(shape: &Shape) -> float {\n"
667 "    match *shape {\n"
668 "        Circle(_, radius) => 0.5 * tau * radius * radius,\n"
669 "        Rectangle(_, ref size) => size.w * size.h\n"
670 "    }\n"
671 "}\n"
672 "~~~\n"
673 msgstr ""
674
675 #. type: Plain text
676 #: doc/tutorial-borrowed-ptr.md:410
677 msgid ""
678 "The first case matches against circles. Here, the pattern extracts the "
679 "radius from the shape variant and the action uses it to compute the area of "
680 "the circle. (Like any up-to-date engineer, we use the [tau circle constant]"
681 "[tau] and not that dreadfully outdated notion of pi)."
682 msgstr ""
683
684 #. type: Plain text
685 #: doc/tutorial-borrowed-ptr.md:412
686 msgid "[tau]: http://www.math.utah.edu/~palais/pi.html"
687 msgstr ""
688
689 #. type: Plain text
690 #: doc/tutorial-borrowed-ptr.md:418
691 msgid ""
692 "The second match is more interesting. Here we match against a rectangle and "
693 "extract its size: but rather than copy the `size` struct, we use a by-"
694 "reference binding to create a pointer to it. In other words, a pattern "
695 "binding like `ref size` binds the name `size` to a pointer of type `&size` "
696 "into the _interior of the enum_."
697 msgstr ""
698
699 #. type: Plain text
700 #: doc/tutorial-borrowed-ptr.md:421
701 msgid ""
702 "To make this more clear, let's look at a diagram of memory layout in the "
703 "case where `shape` points at a rectangle:"
704 msgstr ""
705
706 #. type: Plain text
707 #: doc/tutorial-borrowed-ptr.md:424 doc/tutorial-borrowed-ptr.md:449
708 #, no-wrap
709 msgid ""
710 "~~~ {.notrust}\n"
711 "Stack             Memory\n"
712 msgstr ""
713
714 #. type: Plain text
715 #: doc/tutorial-borrowed-ptr.md:433
716 #, no-wrap
717 msgid ""
718 "+-------+         +---------------+\n"
719 "| shape | ------> | rectangle(    |\n"
720 "+-------+         |   {x: float,  |\n"
721 "| size  | -+      |    y: float}, |\n"
722 "+-------+  +----> |   {w: float,  |\n"
723 "                  |    h: float}) |\n"
724 "                  +---------------+\n"
725 "~~~\n"
726 msgstr ""
727
728 #. type: Plain text
729 #: doc/tutorial-borrowed-ptr.md:440
730 msgid ""
731 "Here you can see that rectangular shapes are composed of five words of "
732 "memory. The first is a tag indicating which variant this enum is "
733 "(`rectangle`, in this case). The next two words are the `x` and `y` fields "
734 "for the point and the remaining two are the `w` and `h` fields for the size. "
735 "The binding `size` is then a pointer into the inside of the shape."
736 msgstr ""
737
738 #. type: Plain text
739 #: doc/tutorial-borrowed-ptr.md:446
740 msgid ""
741 "Perhaps you can see where the danger lies: if the shape were somehow to be "
742 "reassigned, perhaps to a circle, then although the memory used to store that "
743 "shape value would still be valid, _it would have a different type_! The "
744 "following diagram shows what memory would look like if code overwrote "
745 "`shape` with a circle:"
746 msgstr ""
747
748 #. type: Plain text
749 #: doc/tutorial-borrowed-ptr.md:458
750 #, no-wrap
751 msgid ""
752 "+-------+         +---------------+\n"
753 "| shape | ------> | circle(       |\n"
754 "+-------+         |   {x: float,  |\n"
755 "| size  | -+      |    y: float}, |\n"
756 "+-------+  +----> |   float)      |\n"
757 "                  |               |\n"
758 "                  +---------------+\n"
759 "~~~\n"
760 msgstr ""
761
762 #. type: Plain text
763 #: doc/tutorial-borrowed-ptr.md:463
764 msgid ""
765 "As you can see, the `size` pointer would be pointing at a `float` instead of "
766 "a struct. This is not good: dereferencing the second field of a `float` as "
767 "if it were a struct with two fields would be a memory safety violation."
768 msgstr ""
769
770 #. type: Plain text
771 #: doc/tutorial-borrowed-ptr.md:475
772 msgid ""
773 "So, in fact, for every `ref` binding, the compiler will impose the same "
774 "rules as the ones we saw for borrowing the interior of a owned box: it must "
775 "be able to guarantee that the `enum` will not be overwritten for the "
776 "duration of the borrow.  In fact, the compiler would accept the example we "
777 "gave earlier. The example is safe because the shape pointer has type "
778 "`&Shape`, which means \"borrowed pointer to immutable memory containing a "
779 "`shape`\". If, however, the type of that pointer were `&mut Shape`, then the "
780 "ref binding would be ill-typed.  Just as with owned boxes, the compiler will "
781 "permit `ref` bindings into data owned by the stack frame even if the data "
782 "are mutable, but otherwise it requires that the data reside in immutable "
783 "memory."
784 msgstr ""
785
786 #. type: Plain text
787 #: doc/tutorial-borrowed-ptr.md:477
788 msgid "# Returning borrowed pointers"
789 msgstr ""
790
791 #. type: Plain text
792 #: doc/tutorial-borrowed-ptr.md:483
793 msgid ""
794 "So far, all of the examples we have looked at, use borrowed pointers in a "
795 "“downward” direction. That is, a method or code block creates a borrowed "
796 "pointer, then uses it within the same scope. It is also possible to return "
797 "borrowed pointers as the result of a function, but as we'll see, doing so "
798 "requires some explicit annotation."
799 msgstr ""
800
801 #. type: Plain text
802 #: doc/tutorial-borrowed-ptr.md:485
803 msgid "For example, we could write a subroutine like this:"
804 msgstr ""
805
806 #. type: Plain text
807 #: doc/tutorial-borrowed-ptr.md:490
808 msgid ""
809 "~~~ struct Point {x: float, y: float} fn get_x<'r>(p: &'r Point) -> &'r "
810 "float { &p.x } ~~~"
811 msgstr ""
812
813 #. type: Plain text
814 #: doc/tutorial-borrowed-ptr.md:498
815 msgid ""
816 "Here, the function `get_x()` returns a pointer into the structure it was "
817 "given. The type of the parameter (`&'r Point`) and return type (`&'r float`) "
818 "both use a new syntactic form that we have not seen so far.  Here the "
819 "identifier `r` names the lifetime of the pointer explicitly. So in effect, "
820 "this function declares that it takes a pointer with lifetime `r` and returns "
821 "a pointer with that same lifetime."
822 msgstr ""
823
824 #. type: Plain text
825 #: doc/tutorial-borrowed-ptr.md:504
826 msgid ""
827 "In general, it is only possible to return borrowed pointers if they are "
828 "derived from a parameter to the procedure. In that case, the pointer result "
829 "will always have the same lifetime as one of the parameters; named lifetimes "
830 "indicate which parameter that is."
831 msgstr ""
832
833 #. type: Plain text
834 #: doc/tutorial-borrowed-ptr.md:510
835 msgid ""
836 "In the previous examples, function parameter types did not include a "
837 "lifetime name. In those examples, the compiler simply creates a fresh name "
838 "for the lifetime automatically: that is, the lifetime name is guaranteed to "
839 "refer to a distinct lifetime from the lifetimes of all other parameters."
840 msgstr ""
841
842 #. type: Plain text
843 #: doc/tutorial-borrowed-ptr.md:518
844 msgid ""
845 "Named lifetimes that appear in function signatures are conceptually the same "
846 "as the other lifetimes we have seen before, but they are a bit abstract: "
847 "they don’t refer to a specific expression within `get_x()`, but rather to "
848 "some expression within the *caller of `get_x()`*.  The lifetime `r` is "
849 "actually a kind of *lifetime parameter*: it is defined by the caller to "
850 "`get_x()`, just as the value for the parameter `p` is defined by that caller."
851 msgstr ""
852
853 #. type: Plain text
854 #: doc/tutorial-borrowed-ptr.md:523
855 msgid ""
856 "In any case, whatever the lifetime of `r` is, the pointer produced by `&p.x` "
857 "always has the same lifetime as `p` itself: a pointer to a field of a struct "
858 "is valid as long as the struct is valid. Therefore, the compiler accepts the "
859 "function `get_x()`."
860 msgstr ""
861
862 #. type: Plain text
863 #: doc/tutorial-borrowed-ptr.md:526
864 msgid ""
865 "To emphasize this point, let’s look at a variation on the example, this time "
866 "one that does not compile:"
867 msgstr ""
868
869 #. type: Plain text
870 #: doc/tutorial-borrowed-ptr.md:533
871 #, no-wrap
872 msgid ""
873 "~~~ {.xfail-test}\n"
874 "struct Point {x: float, y: float}\n"
875 "fn get_x_sh(p: @Point) -> &float {\n"
876 "    &p.x // Error reported here\n"
877 "}\n"
878 "~~~\n"
879 msgstr ""
880
881 #. type: Plain text
882 #: doc/tutorial-borrowed-ptr.md:541
883 msgid ""
884 "Here, the function `get_x_sh()` takes a managed box as input and returns a "
885 "borrowed pointer. As before, the lifetime of the borrowed pointer that will "
886 "be returned is a parameter (specified by the caller). That means that "
887 "`get_x_sh()` promises to return a borrowed pointer that is valid for as long "
888 "as the caller would like: this is subtly different from the first example, "
889 "which promised to return a pointer that was valid for as long as its pointer "
890 "argument was valid."
891 msgstr ""
892
893 #. type: Plain text
894 #: doc/tutorial-borrowed-ptr.md:552
895 msgid ""
896 "Within `get_x_sh()`, we see the expression `&p.x` which takes the address of "
897 "a field of a managed box. The presence of this expression implies that the "
898 "compiler must guarantee that, so long as the resulting pointer is valid, the "
899 "managed box will not be reclaimed by the garbage collector. But recall that "
900 "`get_x_sh()` also promised to return a pointer that was valid for as long as "
901 "the caller wanted it to be. Clearly, `get_x_sh()` is not in a position to "
902 "make both of these guarantees; in fact, it cannot guarantee that the pointer "
903 "will remain valid at all once it returns, as the parameter `p` may or may "
904 "not be live in the caller. Therefore, the compiler will report an error here."
905 msgstr ""
906
907 #. type: Plain text
908 #: doc/tutorial-borrowed-ptr.md:559
909 msgid ""
910 "In general, if you borrow a managed (or owned) box to create a borrowed "
911 "pointer, the pointer will only be valid within the function and cannot be "
912 "returned. This is why the typical way to return borrowed pointers is to take "
913 "borrowed pointers as input (the only other case in which it can be legal to "
914 "return a borrowed pointer is if the pointer points at a static constant)."
915 msgstr ""
916
917 #. type: Plain text
918 #: doc/tutorial-borrowed-ptr.md:561
919 msgid "# Named lifetimes"
920 msgstr ""
921
922 #. type: Plain text
923 #: doc/tutorial-borrowed-ptr.md:565
924 msgid ""
925 "Let's look at named lifetimes in more detail. Named lifetimes allow for "
926 "grouping of parameters by lifetime. For example, consider this function:"
927 msgstr ""
928
929 #. type: Plain text
930 #: doc/tutorial-borrowed-ptr.md:579
931 #, no-wrap
932 msgid ""
933 "~~~\n"
934 "# struct Point {x: float, y: float}; // as before\n"
935 "# struct Size {w: float, h: float}; // as before\n"
936 "# enum Shape {\n"
937 "#     Circle(Point, float),   // origin, radius\n"
938 "#     Rectangle(Point, Size)  // upper-left, dimensions\n"
939 "# }\n"
940 "# fn compute_area(shape: &Shape) -> float { 0f }\n"
941 "fn select<'r, T>(shape: &'r Shape, threshold: float,\n"
942 "                 a: &'r T, b: &'r T) -> &'r T {\n"
943 "    if compute_area(shape) > threshold {a} else {b}\n"
944 "}\n"
945 "~~~\n"
946 msgstr ""
947
948 #. type: Plain text
949 #: doc/tutorial-borrowed-ptr.md:585
950 msgid ""
951 "This function takes three borrowed pointers and assigns each the same "
952 "lifetime `r`.  In practice, this means that, in the caller, the lifetime `r` "
953 "will be the *intersection of the lifetime of the three region parameters*. "
954 "This may be overly conservative, as in this example:"
955 msgstr ""
956
957 #. type: Plain text
958 #: doc/tutorial-borrowed-ptr.md:607
959 #, no-wrap
960 msgid ""
961 "~~~\n"
962 "# struct Point {x: float, y: float}; // as before\n"
963 "# struct Size {w: float, h: float}; // as before\n"
964 "# enum Shape {\n"
965 "#     Circle(Point, float),   // origin, radius\n"
966 "#     Rectangle(Point, Size)  // upper-left, dimensions\n"
967 "# }\n"
968 "# fn compute_area(shape: &Shape) -> float { 0f }\n"
969 "# fn select<'r, T>(shape: &Shape, threshold: float,\n"
970 "#                  a: &'r T, b: &'r T) -> &'r T {\n"
971 "#     if compute_area(shape) > threshold {a} else {b}\n"
972 "# }\n"
973 "                                                     // -+ r\n"
974 "fn select_based_on_unit_circle<'r, T>(               //  |-+ B\n"
975 "    threshold: float, a: &'r T, b: &'r T) -> &'r T { //  | |\n"
976 "                                                     //  | |\n"
977 "    let shape = Circle(Point {x: 0., y: 0.}, 1.);    //  | |\n"
978 "    select(&shape, threshold, a, b)                  //  | |\n"
979 "}                                                    //  |-+\n"
980 "                                                     // -+\n"
981 "~~~\n"
982 msgstr ""
983
984 #. type: Plain text
985 #: doc/tutorial-borrowed-ptr.md:617
986 msgid ""
987 "In this call to `select()`, the lifetime of the first parameter shape is B, "
988 "the function body. Both of the second two parameters `a` and `b` share the "
989 "same lifetime, `r`, which is a lifetime parameter of "
990 "`select_based_on_unit_circle()`. The caller will infer the intersection of "
991 "these two lifetimes as the lifetime of the returned value, and hence the "
992 "return value of `select()` will be assigned a lifetime of B. This will in "
993 "turn lead to a compilation error, because `select_based_on_unit_circle()` is "
994 "supposed to return a value with the lifetime `r`."
995 msgstr ""
996
997 #. type: Plain text
998 #: doc/tutorial-borrowed-ptr.md:622
999 msgid ""
1000 "To address this, we can modify the definition of `select()` to distinguish "
1001 "the lifetime of the first parameter from the lifetime of the latter two. "
1002 "After all, the first parameter is not being returned. Here is how the new "
1003 "`select()` might look:"
1004 msgstr ""
1005
1006 #. type: Plain text
1007 #: doc/tutorial-borrowed-ptr.md:636
1008 #, no-wrap
1009 msgid ""
1010 "~~~\n"
1011 "# struct Point {x: float, y: float}; // as before\n"
1012 "# struct Size {w: float, h: float}; // as before\n"
1013 "# enum Shape {\n"
1014 "#     Circle(Point, float),   // origin, radius\n"
1015 "#     Rectangle(Point, Size)  // upper-left, dimensions\n"
1016 "# }\n"
1017 "# fn compute_area(shape: &Shape) -> float { 0f }\n"
1018 "fn select<'r, 'tmp, T>(shape: &'tmp Shape, threshold: float,\n"
1019 "                       a: &'r T, b: &'r T) -> &'r T {\n"
1020 "    if compute_area(shape) > threshold {a} else {b}\n"
1021 "}\n"
1022 "~~~\n"
1023 msgstr ""
1024
1025 #. type: Plain text
1026 #: doc/tutorial-borrowed-ptr.md:641
1027 msgid ""
1028 "Here you can see that `shape`'s lifetime is now named `tmp`. The parameters "
1029 "`a`, `b`, and the return value all have the lifetime `r`.  However, since "
1030 "the lifetime `tmp` is not returned, it would be more concise to just omit "
1031 "the named lifetime for `shape` altogether:"
1032 msgstr ""
1033
1034 #. type: Plain text
1035 #: doc/tutorial-borrowed-ptr.md:655
1036 #, no-wrap
1037 msgid ""
1038 "~~~\n"
1039 "# struct Point {x: float, y: float}; // as before\n"
1040 "# struct Size {w: float, h: float}; // as before\n"
1041 "# enum Shape {\n"
1042 "#     Circle(Point, float),   // origin, radius\n"
1043 "#     Rectangle(Point, Size)  // upper-left, dimensions\n"
1044 "# }\n"
1045 "# fn compute_area(shape: &Shape) -> float { 0f }\n"
1046 "fn select<'r, T>(shape: &Shape, threshold: float,\n"
1047 "                 a: &'r T, b: &'r T) -> &'r T {\n"
1048 "    if compute_area(shape) > threshold {a} else {b}\n"
1049 "}\n"
1050 "~~~\n"
1051 msgstr ""
1052
1053 #. type: Plain text
1054 #: doc/tutorial-borrowed-ptr.md:657
1055 msgid "This is equivalent to the previous definition."
1056 msgstr ""
1057
1058 #. type: Plain text
1059 #: doc/tutorial-borrowed-ptr.md:659
1060 msgid "# Conclusion"
1061 msgstr ""
1062
1063 #. type: Plain text
1064 #: doc/tutorial-borrowed-ptr.md:663
1065 msgid ""
1066 "So there you have it: a (relatively) brief tour of the borrowed pointer "
1067 "system. For more details, we refer to the (yet to be written) reference "
1068 "document on borrowed pointers, which will explain the full notation and give "
1069 "more examples."
1070 msgstr ""