rust/doc/po/tutorial-borrowed-ptr.md.pot

1071 lines
36 KiB
Plaintext
Raw Normal View History

# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR The Rust Project Developers
# This file is distributed under the same license as the Rust package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
2013-09-21 23:25:08 +00:00
"Project-Id-Version: Rust 0.8\n"
2013-07-29 22:08:54 +00:00
"POT-Creation-Date: 2013-07-22 23:37+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
2013-07-29 22:08:54 +00:00
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#. type: Plain text
#: doc/rust.md:4 doc/rustpkg.md:4 doc/tutorial.md:4
#: doc/tutorial-borrowed-ptr.md:4 doc/tutorial-ffi.md:4
#: doc/tutorial-macros.md:4 doc/tutorial-tasks.md:4
msgid "# Introduction"
msgstr ""
#. type: Plain text
2013-07-29 22:08:54 +00:00
#: doc/tutorial.md:1108 doc/tutorial-borrowed-ptr.md:72
msgid "Now we can call `compute_distance()` in various ways:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:2
msgid "% Rust Borrowed Pointers Tutorial"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:14
msgid ""
"Borrowed pointers are one of the more flexible and powerful tools available "
"in Rust. A borrowed pointer can point anywhere: into the managed or exchange "
"heap, into the stack, and even into the interior of another data structure. "
"A borrowed pointer is as flexible as a C pointer or C++ reference. However, "
"unlike C and C++ compilers, the Rust compiler includes special static checks "
"that ensure that programs use borrowed pointers safely. Another advantage of "
"borrowed pointers is that they are invisible to the garbage collector, so "
"working with borrowed pointers helps reduce the overhead of automatic memory "
"management."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:18
msgid ""
"Despite their complete safety, a borrowed pointer's representation at "
"runtime is the same as that of an ordinary pointer in a C program. They "
"introduce zero overhead. The compiler does all safety checks at compile time."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:24
msgid ""
"Although borrowed pointers have rather elaborate theoretical underpinnings "
"(region pointers), the core concepts will be familiar to anyone who has "
2013-07-29 22:08:54 +00:00
"worked with C or C++. Therefore, the best way to explain how they are used—"
"and their limitations—is probably just to work through several examples."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:26
msgid "# By example"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:31
msgid ""
"Borrowed pointers are called *borrowed* because they are only valid for a "
"limited duration. Borrowed pointers never claim any kind of ownership over "
"the data that they point to: instead, they are used for cases where you "
"would like to use data for a short time."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:33
msgid "As an example, consider a simple struct type `Point`:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:37
msgid "~~~ struct Point {x: float, y: float} ~~~"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:41
msgid ""
"We can use this simple definition to allocate points in many different ways. "
"For example, in this code, each of these three local variables contains a "
"point, but allocated in a different place:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:48
#, no-wrap
msgid ""
"~~~\n"
"# struct Point {x: float, y: float}\n"
"let on_the_stack : Point = Point {x: 3.0, y: 4.0};\n"
"let managed_box : @Point = @Point {x: 5.0, y: 1.0};\n"
"let owned_box : ~Point = ~Point {x: 7.0, y: 9.0};\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:60
msgid ""
"Suppose we wanted to write a procedure that computed the distance between "
"any two points, no matter where they were stored. For example, we might like "
"to compute the distance between `on_the_stack` and `managed_box`, or between "
"`managed_box` and `owned_box`. One option is to define a function that takes "
2013-07-29 22:08:54 +00:00
"two arguments of type `Point`—that is, it takes the points by value. But if "
"we define it this way, calling the function will cause the points to be "
"copied. For points, this is probably not so bad, but often copies are "
"expensive. Worse, if the data type contains mutable fields, copying can "
"change the semantics of your program in unexpected ways. So we'd like to "
"define a function that takes the points by pointer. We can use borrowed "
"pointers to do this:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:70
#, no-wrap
msgid ""
"~~~\n"
"# struct Point {x: float, y: float}\n"
"# fn sqrt(f: float) -> float { 0f }\n"
"fn compute_distance(p1: &Point, p2: &Point) -> float {\n"
" let x_d = p1.x - p2.x;\n"
" let y_d = p1.y - p2.y;\n"
" sqrt(x_d * x_d + y_d * y_d)\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:82
#, no-wrap
msgid ""
"~~~\n"
"# struct Point {x: float, y: float}\n"
"# let on_the_stack : Point = Point{x: 3.0, y: 4.0};\n"
"# let managed_box : @Point = @Point{x: 5.0, y: 1.0};\n"
"# let owned_box : ~Point = ~Point{x: 7.0, y: 9.0};\n"
"# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }\n"
"compute_distance(&on_the_stack, managed_box);\n"
"compute_distance(managed_box, owned_box);\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:89
msgid ""
"Here, the `&` operator takes the address of the variable `on_the_stack`; "
"this is because `on_the_stack` has the type `Point` (that is, a struct "
"value) and we have to take its address to get a value. We also call this "
"_borrowing_ the local variable `on_the_stack`, because we have created an "
"alias: that is, another name for the same data."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:95
msgid ""
"In contrast, we can pass the boxes `managed_box` and `owned_box` to "
"`compute_distance` directly. The compiler automatically converts a box like "
"`@Point` or `~Point` to a borrowed pointer like `&Point`. This is another "
"form of borrowing: in this case, the caller lends the contents of the "
"managed or owned box to the callee."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:105
msgid ""
"Whenever a caller lends data to a callee, there are some limitations on what "
"the caller can do with the original. For example, if the contents of a "
"variable have been lent out, you cannot send that variable to another task. "
"In addition, the compiler will reject any code that might cause the borrowed "
"value to be freed or overwrite its component fields with values of different "
"types (I'll get into what kinds of actions those are shortly). This rule "
"should make intuitive sense: you must wait for a borrower to return the "
"value that you lent it (that is, wait for the borrowed pointer to go out of "
"scope) before you can make full use of it again."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:107
msgid "# Other uses for the & operator"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:109
msgid "In the previous example, the value `on_the_stack` was defined like so:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:114
msgid ""
"~~~ # struct Point {x: float, y: float} let on_the_stack: Point = Point {x: "
"3.0, y: 4.0}; ~~~"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:119
msgid ""
"This declaration means that code can only pass `Point` by value to other "
"functions. As a consequence, we had to explicitly take the address of "
"`on_the_stack` to get a borrowed pointer. Sometimes however it is more "
"convenient to move the & operator into the definition of `on_the_stack`:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:124
msgid ""
"~~~ # struct Point {x: float, y: float} let on_the_stack2: &Point = &Point "
"{x: 3.0, y: 4.0}; ~~~"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:128
msgid ""
"Applying `&` to an rvalue (non-assignable location) is just a convenient "
"shorthand for creating a temporary and taking its address. A more verbose "
"way to write the same code is:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:134
msgid ""
"~~~ # struct Point {x: float, y: float} let tmp = Point {x: 3.0, y: 4.0}; "
"let on_the_stack2 : &Point = &tmp; ~~~"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:136
msgid "# Taking the address of fields"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:141
msgid ""
"As in C, the `&` operator is not limited to taking the address of local "
"variables. It can also take the address of fields or individual array "
"elements. For example, consider this type definition for `rectangle`:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:147
msgid ""
"~~~ struct Point {x: float, y: float} // as before struct Size {w: float, h: "
"float} // as before struct Rectangle {origin: Point, size: Size} ~~~"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:149
msgid "Now, as before, we can define rectangles in a few different ways:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:161
#, no-wrap
msgid ""
"~~~\n"
"# struct Point {x: float, y: float}\n"
"# struct Size {w: float, h: float} // as before\n"
"# struct Rectangle {origin: Point, size: Size}\n"
"let rect_stack = &Rectangle {origin: Point {x: 1f, y: 2f},\n"
" size: Size {w: 3f, h: 4f}};\n"
"let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f},\n"
" size: Size {w: 3f, h: 4f}};\n"
"let rect_owned = ~Rectangle {origin: Point {x: 5f, y: 6f},\n"
" size: Size {w: 3f, h: 4f}};\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:164
msgid ""
"In each case, we can extract out individual subcomponents with the `&` "
"operator. For example, I could write:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:175
msgid ""
"~~~ # struct Point {x: float, y: float} // as before # struct Size {w: "
"float, h: float} // as before # struct Rectangle {origin: Point, size: Size} "
"# let rect_stack = &Rectangle {origin: Point {x: 1f, y: 2f}, size: Size {w: "
"3f, h: 4f}}; # let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f}, "
"size: Size {w: 3f, h: 4f}}; # let rect_owned = ~Rectangle {origin: Point {x: "
"5f, y: 6f}, size: Size {w: 3f, h: 4f}}; # fn compute_distance(p1: &Point, "
"p2: &Point) -> float { 0f } compute_distance(&rect_stack.origin, "
"&rect_managed.origin); ~~~"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:178
msgid ""
"which would borrow the field `origin` from the rectangle on the stack as "
"well as from the managed box, and then compute the distance between them."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:180
msgid "# Borrowing managed boxes and rooting"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:186
msgid ""
2013-07-29 22:08:54 +00:00
"Weve seen a few examples so far of borrowing heap boxes, both managed and "
"owned. Up till this point, weve glossed over issues of safety. As stated in "
"the introduction, at runtime a borrowed pointer is simply a pointer, nothing "
"more. Therefore, avoiding C's problems with dangling pointers requires a "
"compile-time safety check."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:197
msgid ""
"The basis for the check is the notion of _lifetimes_. A lifetime is a static "
"approximation of the span of execution during which the pointer is valid: it "
"always corresponds to some expression or block within the program. Code "
"inside that expression can use the pointer without restrictions. But if the "
"pointer escapes from that expression (for example, if the expression "
"contains an assignment expression that assigns the pointer to a mutable "
"field of a data structure with a broader scope than the pointer itself), the "
"compiler reports an error. We'll be discussing lifetimes more in the "
"examples to come, and a more thorough introduction is also available."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:202
msgid ""
"When the `&` operator creates a borrowed pointer, the compiler must ensure "
"that the pointer remains valid for its entire lifetime. Sometimes this is "
"relatively easy, such as when taking the address of a local variable or a "
"field that is stored on the stack:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:211
#, no-wrap
msgid ""
"~~~\n"
"struct X { f: int }\n"
"fn example1() {\n"
" let mut x = X { f: 3 };\n"
" let y = &mut x.f; // -+ L\n"
" ... // |\n"
"} // -+\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:216
msgid ""
"Here, the lifetime of the borrowed pointer `y` is simply L, the remainder of "
"the function body. The compiler need not do any other work to prove that "
"code will not free `x.f`. This is true even if the code mutates `x`."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:218
msgid "The situation gets more complex when borrowing data inside heap boxes:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:227
#, no-wrap
msgid ""
"~~~\n"
"# struct X { f: int }\n"
"fn example2() {\n"
" let mut x = @X { f: 3 };\n"
" let y = &x.f; // -+ L\n"
" ... // |\n"
"} // -+\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:238
msgid ""
"In this example, the value `x` is a heap box, and `y` is therefore a pointer "
"into that heap box. Again the lifetime of `y` is L, the remainder of the "
"function body. But there is a crucial difference: suppose `x` were to be "
"reassigned during the lifetime L? If the compiler isn't careful, the managed "
"box could become *unrooted*, and would therefore be subject to garbage "
"collection. A heap box that is unrooted is one such that no pointer values "
"in the heap point to it. It would violate memory safety for the box that was "
"originally assigned to `x` to be garbage-collected, since a non-heap pointer "
"*`y`* still points into it."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:241
msgid ""
"> ***Note:*** Our current implementation implements the garbage collector > "
"using reference counting and cycle detection."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:247
msgid ""
"For this reason, whenever an `&` expression borrows the interior of a "
"managed box stored in a mutable location, the compiler inserts a temporary "
"that ensures that the managed box remains live for the entire lifetime. So, "
"the above example would be compiled as if it were written"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:257
#, no-wrap
msgid ""
"~~~\n"
"# struct X { f: int }\n"
"fn example2() {\n"
" let mut x = @X {f: 3};\n"
" let x1 = x;\n"
" let y = &x1.f; // -+ L\n"
" ... // |\n"
"} // -+\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:260
msgid ""
"Now if `x` is reassigned, the pointer `y` will still remain valid. This "
"process is called *rooting*."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:262
msgid "# Borrowing owned boxes"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:268
msgid ""
"The previous example demonstrated *rooting*, the process by which the "
"compiler ensures that managed boxes remain live for the duration of a "
"borrow. Unfortunately, rooting does not work for borrows of owned boxes, "
"because it is not possible to have two references to a owned box."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:274
msgid ""
"For owned boxes, therefore, the compiler will only allow a borrow *if the "
"compiler can guarantee that the owned box will not be reassigned or moved "
"for the lifetime of the pointer*. This does not necessarily mean that the "
"owned box is stored in immutable memory. For example, the following function "
"is legal:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:289
#, no-wrap
msgid ""
"~~~\n"
"# fn some_condition() -> bool { true }\n"
"# struct Foo { f: int }\n"
"fn example3() -> int {\n"
" let mut x = ~Foo {f: 3};\n"
" if some_condition() {\n"
" let y = &x.f; // -+ L\n"
" return *y; // |\n"
" } // -+\n"
" x = ~Foo {f: 4};\n"
" ...\n"
"# return 0;\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:295
msgid ""
"Here, as before, the interior of the variable `x` is being borrowed and `x` "
"is declared as mutable. However, the compiler can prove that `x` is not "
"assigned anywhere in the lifetime L of the variable `y`. Therefore, it "
"accepts the function, even though `x` is mutable and in fact is mutated "
"later in the function."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:301
msgid ""
"It may not be clear why we are so concerned about mutating a borrowed "
"variable. The reason is that the runtime system frees any owned box _as soon "
"as its owning reference changes or goes out of scope_. Therefore, a program "
"like this is illegal (and would be rejected by the compiler):"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:310
#, no-wrap
msgid ""
"~~~ {.xfail-test}\n"
"fn example3() -> int {\n"
" let mut x = ~X {f: 3};\n"
" let y = &x.f;\n"
" x = ~X {f: 4}; // Error reported here.\n"
" *y\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:313
msgid ""
"To make this clearer, consider this diagram showing the state of memory "
"immediately before the re-assignment of `x`:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:316 doc/tutorial-borrowed-ptr.md:330
#, no-wrap
msgid ""
"~~~ {.notrust}\n"
" Stack Exchange Heap\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:325
#, no-wrap
msgid ""
" x +----------+\n"
" | ~{f:int} | ----+\n"
" y +----------+ |\n"
" | &int | ----+\n"
" +----------+ | +---------+\n"
" +--> | f: 3 |\n"
" +---------+\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:327
msgid "Once the reassignment occurs, the memory will look like this:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:339
#, no-wrap
msgid ""
" x +----------+ +---------+\n"
" | ~{f:int} | -------> | f: 4 |\n"
" y +----------+ +---------+\n"
" | &int | ----+\n"
" +----------+ | +---------+\n"
" +--> | (freed) |\n"
" +---------+\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:342
msgid ""
"Here you can see that the variable `y` still points at the old box, which "
"has been freed."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:348
msgid ""
"In fact, the compiler can apply the same kind of reasoning to any memory "
"that is _(uniquely) owned by the stack frame_. So we could modify the "
"previous example to introduce additional owned pointers and structs, and the "
"compiler will still be able to detect possible mutations:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:353
#, no-wrap
msgid ""
"~~~ {.xfail-test}\n"
"fn example3() -> int {\n"
" struct R { g: int }\n"
" struct S { f: ~R }\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:361
#, no-wrap
msgid ""
" let mut x = ~S {f: ~R {g: 3}};\n"
" let y = &x.f.g;\n"
" x = ~S {f: ~R {g: 4}}; // Error reported here.\n"
" x.f = ~R {g: 5}; // Error reported here.\n"
" *y\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:365
msgid ""
"In this case, two errors are reported, one when the variable `x` is modified "
"and another when `x.f` is modified. Either modification would invalidate the "
"pointer `y`."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:367
msgid "# Borrowing and enums"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:373
msgid ""
"The previous example showed that the type system forbids any borrowing of "
"owned boxes found in aliasable, mutable memory. This restriction prevents "
"pointers from pointing into freed memory. There is one other case where the "
"compiler must be very careful to ensure that pointers remain valid: pointers "
"into the interior of an `enum`."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:376
msgid ""
2013-07-29 22:08:54 +00:00
"As an example, lets look at the following `shape` type that can represent "
"both rectangles and circles:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:385
#, no-wrap
msgid ""
"~~~\n"
"struct Point {x: float, y: float}; // as before\n"
"struct Size {w: float, h: float}; // as before\n"
"enum Shape {\n"
" Circle(Point, float), // origin, radius\n"
" Rectangle(Point, Size) // upper-left, dimensions\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:389
msgid ""
"Now we might write a function to compute the area of a shape. This function "
"takes a borrowed pointer to a shape, to avoid the need for copying."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:405
#, no-wrap
msgid ""
"~~~\n"
"# struct Point {x: float, y: float}; // as before\n"
"# struct Size {w: float, h: float}; // as before\n"
"# enum Shape {\n"
"# Circle(Point, float), // origin, radius\n"
"# Rectangle(Point, Size) // upper-left, dimensions\n"
"# }\n"
"# static tau: float = 6.28f;\n"
"fn compute_area(shape: &Shape) -> float {\n"
" match *shape {\n"
" Circle(_, radius) => 0.5 * tau * radius * radius,\n"
" Rectangle(_, ref size) => size.w * size.h\n"
" }\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:410
msgid ""
"The first case matches against circles. Here, the pattern extracts the "
"radius from the shape variant and the action uses it to compute the area of "
"the circle. (Like any up-to-date engineer, we use the [tau circle constant]"
"[tau] and not that dreadfully outdated notion of pi)."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:412
msgid "[tau]: http://www.math.utah.edu/~palais/pi.html"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:418
msgid ""
"The second match is more interesting. Here we match against a rectangle and "
"extract its size: but rather than copy the `size` struct, we use a by-"
"reference binding to create a pointer to it. In other words, a pattern "
"binding like `ref size` binds the name `size` to a pointer of type `&size` "
"into the _interior of the enum_."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:421
msgid ""
"To make this more clear, let's look at a diagram of memory layout in the "
"case where `shape` points at a rectangle:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:424 doc/tutorial-borrowed-ptr.md:449
#, no-wrap
msgid ""
"~~~ {.notrust}\n"
"Stack Memory\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:433
#, no-wrap
msgid ""
"+-------+ +---------------+\n"
"| shape | ------> | rectangle( |\n"
"+-------+ | {x: float, |\n"
"| size | -+ | y: float}, |\n"
"+-------+ +----> | {w: float, |\n"
" | h: float}) |\n"
" +---------------+\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:440
msgid ""
"Here you can see that rectangular shapes are composed of five words of "
"memory. The first is a tag indicating which variant this enum is "
"(`rectangle`, in this case). The next two words are the `x` and `y` fields "
"for the point and the remaining two are the `w` and `h` fields for the size. "
"The binding `size` is then a pointer into the inside of the shape."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:446
msgid ""
"Perhaps you can see where the danger lies: if the shape were somehow to be "
"reassigned, perhaps to a circle, then although the memory used to store that "
"shape value would still be valid, _it would have a different type_! The "
"following diagram shows what memory would look like if code overwrote "
"`shape` with a circle:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:458
#, no-wrap
msgid ""
"+-------+ +---------------+\n"
"| shape | ------> | circle( |\n"
"+-------+ | {x: float, |\n"
"| size | -+ | y: float}, |\n"
"+-------+ +----> | float) |\n"
" | |\n"
" +---------------+\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:463
msgid ""
"As you can see, the `size` pointer would be pointing at a `float` instead of "
"a struct. This is not good: dereferencing the second field of a `float` as "
"if it were a struct with two fields would be a memory safety violation."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:475
msgid ""
"So, in fact, for every `ref` binding, the compiler will impose the same "
"rules as the ones we saw for borrowing the interior of a owned box: it must "
"be able to guarantee that the `enum` will not be overwritten for the "
"duration of the borrow. In fact, the compiler would accept the example we "
"gave earlier. The example is safe because the shape pointer has type "
"`&Shape`, which means \"borrowed pointer to immutable memory containing a "
"`shape`\". If, however, the type of that pointer were `&mut Shape`, then the "
"ref binding would be ill-typed. Just as with owned boxes, the compiler will "
"permit `ref` bindings into data owned by the stack frame even if the data "
"are mutable, but otherwise it requires that the data reside in immutable "
"memory."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:477
msgid "# Returning borrowed pointers"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:483
msgid ""
"So far, all of the examples we have looked at, use borrowed pointers in a "
2013-07-29 22:08:54 +00:00
"“downward” direction. That is, a method or code block creates a borrowed "
"pointer, then uses it within the same scope. It is also possible to return "
"borrowed pointers as the result of a function, but as we'll see, doing so "
"requires some explicit annotation."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:485
msgid "For example, we could write a subroutine like this:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:490
msgid ""
"~~~ struct Point {x: float, y: float} fn get_x<'r>(p: &'r Point) -> &'r "
"float { &p.x } ~~~"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:498
msgid ""
"Here, the function `get_x()` returns a pointer into the structure it was "
"given. The type of the parameter (`&'r Point`) and return type (`&'r float`) "
"both use a new syntactic form that we have not seen so far. Here the "
"identifier `r` names the lifetime of the pointer explicitly. So in effect, "
"this function declares that it takes a pointer with lifetime `r` and returns "
"a pointer with that same lifetime."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:504
msgid ""
"In general, it is only possible to return borrowed pointers if they are "
"derived from a parameter to the procedure. In that case, the pointer result "
"will always have the same lifetime as one of the parameters; named lifetimes "
"indicate which parameter that is."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:510
msgid ""
"In the previous examples, function parameter types did not include a "
"lifetime name. In those examples, the compiler simply creates a fresh name "
"for the lifetime automatically: that is, the lifetime name is guaranteed to "
"refer to a distinct lifetime from the lifetimes of all other parameters."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:518
msgid ""
"Named lifetimes that appear in function signatures are conceptually the same "
"as the other lifetimes we have seen before, but they are a bit abstract: "
2013-07-29 22:08:54 +00:00
"they dont refer to a specific expression within `get_x()`, but rather to "
"some expression within the *caller of `get_x()`*. The lifetime `r` is "
"actually a kind of *lifetime parameter*: it is defined by the caller to "
"`get_x()`, just as the value for the parameter `p` is defined by that caller."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:523
msgid ""
"In any case, whatever the lifetime of `r` is, the pointer produced by `&p.x` "
"always has the same lifetime as `p` itself: a pointer to a field of a struct "
"is valid as long as the struct is valid. Therefore, the compiler accepts the "
"function `get_x()`."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:526
msgid ""
2013-07-29 22:08:54 +00:00
"To emphasize this point, lets look at a variation on the example, this time "
"one that does not compile:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:533
#, no-wrap
msgid ""
"~~~ {.xfail-test}\n"
"struct Point {x: float, y: float}\n"
"fn get_x_sh(p: @Point) -> &float {\n"
" &p.x // Error reported here\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:541
msgid ""
"Here, the function `get_x_sh()` takes a managed box as input and returns a "
"borrowed pointer. As before, the lifetime of the borrowed pointer that will "
"be returned is a parameter (specified by the caller). That means that "
"`get_x_sh()` promises to return a borrowed pointer that is valid for as long "
"as the caller would like: this is subtly different from the first example, "
"which promised to return a pointer that was valid for as long as its pointer "
"argument was valid."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:552
msgid ""
"Within `get_x_sh()`, we see the expression `&p.x` which takes the address of "
"a field of a managed box. The presence of this expression implies that the "
"compiler must guarantee that, so long as the resulting pointer is valid, the "
"managed box will not be reclaimed by the garbage collector. But recall that "
"`get_x_sh()` also promised to return a pointer that was valid for as long as "
"the caller wanted it to be. Clearly, `get_x_sh()` is not in a position to "
"make both of these guarantees; in fact, it cannot guarantee that the pointer "
"will remain valid at all once it returns, as the parameter `p` may or may "
"not be live in the caller. Therefore, the compiler will report an error here."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:559
msgid ""
"In general, if you borrow a managed (or owned) box to create a borrowed "
"pointer, the pointer will only be valid within the function and cannot be "
"returned. This is why the typical way to return borrowed pointers is to take "
"borrowed pointers as input (the only other case in which it can be legal to "
"return a borrowed pointer is if the pointer points at a static constant)."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:561
msgid "# Named lifetimes"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:565
msgid ""
"Let's look at named lifetimes in more detail. Named lifetimes allow for "
"grouping of parameters by lifetime. For example, consider this function:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:579
#, no-wrap
msgid ""
"~~~\n"
"# struct Point {x: float, y: float}; // as before\n"
"# struct Size {w: float, h: float}; // as before\n"
"# enum Shape {\n"
"# Circle(Point, float), // origin, radius\n"
"# Rectangle(Point, Size) // upper-left, dimensions\n"
"# }\n"
"# fn compute_area(shape: &Shape) -> float { 0f }\n"
"fn select<'r, T>(shape: &'r Shape, threshold: float,\n"
" a: &'r T, b: &'r T) -> &'r T {\n"
" if compute_area(shape) > threshold {a} else {b}\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:585
msgid ""
"This function takes three borrowed pointers and assigns each the same "
"lifetime `r`. In practice, this means that, in the caller, the lifetime `r` "
"will be the *intersection of the lifetime of the three region parameters*. "
"This may be overly conservative, as in this example:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:607
#, no-wrap
msgid ""
"~~~\n"
"# struct Point {x: float, y: float}; // as before\n"
"# struct Size {w: float, h: float}; // as before\n"
"# enum Shape {\n"
"# Circle(Point, float), // origin, radius\n"
"# Rectangle(Point, Size) // upper-left, dimensions\n"
"# }\n"
"# fn compute_area(shape: &Shape) -> float { 0f }\n"
"# fn select<'r, T>(shape: &Shape, threshold: float,\n"
"# a: &'r T, b: &'r T) -> &'r T {\n"
"# if compute_area(shape) > threshold {a} else {b}\n"
"# }\n"
" // -+ r\n"
"fn select_based_on_unit_circle<'r, T>( // |-+ B\n"
" threshold: float, a: &'r T, b: &'r T) -> &'r T { // | |\n"
" // | |\n"
" let shape = Circle(Point {x: 0., y: 0.}, 1.); // | |\n"
" select(&shape, threshold, a, b) // | |\n"
"} // |-+\n"
" // -+\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:617
msgid ""
"In this call to `select()`, the lifetime of the first parameter shape is B, "
"the function body. Both of the second two parameters `a` and `b` share the "
"same lifetime, `r`, which is a lifetime parameter of "
"`select_based_on_unit_circle()`. The caller will infer the intersection of "
"these two lifetimes as the lifetime of the returned value, and hence the "
"return value of `select()` will be assigned a lifetime of B. This will in "
"turn lead to a compilation error, because `select_based_on_unit_circle()` is "
"supposed to return a value with the lifetime `r`."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:622
msgid ""
"To address this, we can modify the definition of `select()` to distinguish "
"the lifetime of the first parameter from the lifetime of the latter two. "
"After all, the first parameter is not being returned. Here is how the new "
"`select()` might look:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:636
#, no-wrap
msgid ""
"~~~\n"
"# struct Point {x: float, y: float}; // as before\n"
"# struct Size {w: float, h: float}; // as before\n"
"# enum Shape {\n"
"# Circle(Point, float), // origin, radius\n"
"# Rectangle(Point, Size) // upper-left, dimensions\n"
"# }\n"
"# fn compute_area(shape: &Shape) -> float { 0f }\n"
"fn select<'r, 'tmp, T>(shape: &'tmp Shape, threshold: float,\n"
" a: &'r T, b: &'r T) -> &'r T {\n"
" if compute_area(shape) > threshold {a} else {b}\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:641
msgid ""
"Here you can see that `shape`'s lifetime is now named `tmp`. The parameters "
"`a`, `b`, and the return value all have the lifetime `r`. However, since "
"the lifetime `tmp` is not returned, it would be more concise to just omit "
"the named lifetime for `shape` altogether:"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:655
#, no-wrap
msgid ""
"~~~\n"
"# struct Point {x: float, y: float}; // as before\n"
"# struct Size {w: float, h: float}; // as before\n"
"# enum Shape {\n"
"# Circle(Point, float), // origin, radius\n"
"# Rectangle(Point, Size) // upper-left, dimensions\n"
"# }\n"
"# fn compute_area(shape: &Shape) -> float { 0f }\n"
"fn select<'r, T>(shape: &Shape, threshold: float,\n"
" a: &'r T, b: &'r T) -> &'r T {\n"
" if compute_area(shape) > threshold {a} else {b}\n"
"}\n"
"~~~\n"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:657
msgid "This is equivalent to the previous definition."
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:659
msgid "# Conclusion"
msgstr ""
#. type: Plain text
#: doc/tutorial-borrowed-ptr.md:663
msgid ""
"So there you have it: a (relatively) brief tour of the borrowed pointer "
"system. For more details, we refer to the (yet to be written) reference "
"document on borrowed pointers, which will explain the full notation and give "
"more examples."
msgstr ""