diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2013-02-26 10:02:36 -0800 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2013-02-26 10:02:36 -0800 |
| commit | c9dd917fad8ead284643b9873de60e3df894fb59 (patch) | |
| tree | 6722e7ca5ce29d2abf19869475220d7ee1b282b7 | |
| parent | 4a9d4aa52e70eba52dad0719ed6e1eca95f1a2cc (diff) | |
| download | rust-c9dd917fad8ead284643b9873de60e3df894fb59.tar.gz rust-c9dd917fad8ead284643b9873de60e3df894fb59.zip | |
doc: Remove references to mut fields. rs=demuting
| -rw-r--r-- | doc/rust.md | 4 | ||||
| -rw-r--r-- | doc/tutorial-borrowed-ptr.md | 161 | ||||
| -rw-r--r-- | doc/tutorial-ffi.md | 14 | ||||
| -rw-r--r-- | doc/tutorial.md | 27 |
4 files changed, 25 insertions, 181 deletions
diff --git a/doc/rust.md b/doc/rust.md index 975e4bbb8a2..9a3d087f3d7 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1610,11 +1610,11 @@ The following are examples of structure expressions: ~~~~ # struct Point { x: float, y: float } # struct TuplePoint(float, float); -# mod game { pub struct User { name: &str, age: uint, mut score: uint } } +# mod game { pub struct User { name: &str, age: uint, score: uint } } # use game; Point {x: 10f, y: 20f}; TuplePoint(10f, 20f); -let u = game::User {name: "Joe", age: 35u, mut score: 100_000}; +let u = game::User {name: "Joe", age: 35u, score: 100_000}; ~~~~ A structure expression forms a new value of the named structure type. diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md index c13b2528598..0c1624706bf 100644 --- a/doc/tutorial-borrowed-ptr.md +++ b/doc/tutorial-borrowed-ptr.md @@ -348,12 +348,12 @@ mutations: ~~~ {.xfail-test} fn example3() -> int { struct R { g: int } - struct S { mut f: ~R } + struct S { f: ~R } - let mut x = ~S {mut f: ~R {g: 3}}; + let mut x = ~S {f: ~R {g: 3}}; let y = &x.f.g; - x = ~S {mut f: ~R {g: 4}}; // Error reported here. - x.f = ~R {g: 5}; // Error reported here. + x = ~S {f: ~R {g: 4}}; // Error reported here. + x.f = ~R {g: 5}; // Error reported here. *y } ~~~ @@ -362,91 +362,6 @@ 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`. -Things get trickier when the unique box is not uniquely owned by the -stack frame, or when there is no way for the compiler to determine the -box's owner. Consider a program like this: - -~~~ {.xfail-test} -struct R { g: int } -struct S { mut f: ~R } -fn example5a(x: @S, callback: @fn()) -> int { - let y = &x.f.g; // Error reported here. - ... - callback(); - ... -# return 0; -} -~~~ - -Here the heap looks something like: - -~~~ {.notrust} - Stack Managed Heap Exchange Heap - - x +------+ +-------------+ +------+ - | @... | ----> | mut f: ~... | --+-> | g: 3 | - y +------+ +-------------+ | +------+ - | &int | -------------------------+ - +------+ -~~~ - -In this case, the owning reference to the value being borrowed is -`x.f`. Moreover, `x.f` is both mutable and *aliasable*. Aliasable -means that there may be other pointers to that same managed box, so -even if the compiler were to prove an absence of mutations to `x.f`, -code could mutate `x.f` indirectly by changing an alias of -`x`. Therefore, to be safe, the compiler only accepts *pure* actions -during the lifetime of `y`. We define what "pure" means in the section -on [purity](#purity). - -Besides ensuring purity, the only way to borrow the interior of a -unique found in aliasable memory is to ensure that the borrowed field -itself is also unique, as in the following example: - -~~~ -struct R { g: int } -struct S { f: ~R } -fn example5b(x: @S) -> int { - let y = &x.f.g; - ... -# return 0; -} -~~~ - -Here, the field `f` is not declared as mutable. But that is enough for -the compiler to know that, even if aliases to `x` exist, the field `f` -cannot be changed and hence the unique box `g` will remain valid. - -If you do have a unique box in a mutable field, and you wish to borrow -it, one option is to use the swap operator to move that unique box -onto your stack: - -~~~ -struct R { g: int } -struct S { mut f: ~R } -fn example5c(x: @S) -> int { - let mut v = ~R {g: 0}; - v <-> x.f; // Swap v and x.f - { // Block constrains the scope of `y`: - let y = &v.g; - ... - } - x.f = v; // Replace x.f - ... -# return 0; -} -~~~ - -Of course, this has the side effect of modifying your managed box for -the duration of the borrow, so it only works when you know that you -won't be accessing that same box for the duration of the loan. Also, -it is sometimes necessary to introduce additional blocks to constrain -the scope of the loan. In this example, the borrowed pointer `y` -would still be in scope when you moved the value `v` back into `x.f`, -and hence moving `v` would be considered illegal. You cannot move -values if they are the targets of valid outstanding loans. Introducing -the block restricts the scope of `y`, making the move legal. - # Borrowing and enums The previous example showed that the type system forbids any borrowing @@ -558,11 +473,6 @@ 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. -> ***Note:*** Right now, pattern bindings not explicitly annotated -> with `ref` or `copy` use a special mode of "implicit by reference". -> This is changing as soon as we finish updating all the existing code -> in the compiler that relies on the current settings. - # Returning borrowed pointers So far, all of the examples we've looked at use borrowed pointers in a @@ -745,69 +655,6 @@ fn select<T>(shape: &Shape, threshold: float, This is equivalent to the previous definition. -# Purity - -As mentioned before, the Rust compiler offers a kind of escape hatch -that permits borrowing of any data, as long as the actions that occur -during the lifetime of the borrow are pure. Pure actions are those -that only modify data owned by the current stack frame. The compiler -can therefore permit arbitrary pointers into the heap, secure in the -knowledge that no pure action will ever cause them to become -invalidated (the compiler must still track data on the stack which is -borrowed and enforce those rules normally, of course). A pure function -in Rust is referentially transparent: it returns the same results -given the same (observably equivalent) inputs. That is because while -pure functions are allowed to modify data, they may only modify -*stack-local* data, which cannot be observed outside the scope of the -function itself. (Using an `unsafe` block invalidates this guarantee.) - -Let’s revisit a previous example and show how purity can affect -typechecking. Here is `example5a()`, which borrows the interior of a -unique box found in an aliasable, mutable location, only now we’ve -replaced the `...` with some specific code: - -~~~ -struct R { g: int } -struct S { mut f: ~R } -fn example5a(x: @S ...) -> int { - let y = &x.f.g; // Unsafe - *y + 1 -} -~~~ - -The new code simply returns an incremented version of `y`. This code -clearly doesn't mutate the heap, so the compiler is satisfied. - -But suppose we wanted to pull the increment code into a helper, like -this: - -~~~ -fn add_one(x: &int) -> int { *x + 1 } -~~~ - -We can now update `example5a()` to use `add_one()`: - -~~~ -# struct R { g: int } -# struct S { mut f: ~R } -# pure fn add_one(x: &int) -> int { *x + 1 } -fn example5a(x: @S ...) -> int { - let y = &x.f.g; - add_one(y) // Error reported here -} -~~~ - -But now the compiler will report an error again. The reason is that it -only considers one function at a time (like most typecheckers), and -so it does not know that `add_one()` consists of pure code. We can -help the compiler by labeling `add_one()` as pure: - -~~~ -pure fn add_one(x: &int) -> int { *x + 1 } -~~~ - -With this change, the modified version of `example5a()` will again compile. - # Conclusion So there you have it: a (relatively) brief tour of the borrowed pointer diff --git a/doc/tutorial-ffi.md b/doc/tutorial-ffi.md index c3def1f4b27..b7659376ed6 100644 --- a/doc/tutorial-ffi.md +++ b/doc/tutorial-ffi.md @@ -220,21 +220,21 @@ extern mod std; use libc::c_ulonglong; struct timeval { - mut tv_sec: c_ulonglong, - mut tv_usec: c_ulonglong + tv_sec: c_ulonglong, + tv_usec: c_ulonglong } #[nolink] extern mod lib_c { - fn gettimeofday(tv: *timeval, tz: *()) -> i32; + fn gettimeofday(tv: *mut timeval, tz: *()) -> i32; } fn unix_time_in_microseconds() -> u64 { unsafe { - let x = timeval { - mut tv_sec: 0 as c_ulonglong, - mut tv_usec: 0 as c_ulonglong + let mut x = timeval { + tv_sec: 0 as c_ulonglong, + tv_usec: 0 as c_ulonglong }; - lib_c::gettimeofday(ptr::addr_of(&x), ptr::null()); + lib_c::gettimeofday(&mut x, ptr::null()); return (x.tv_sec as u64) * 1000_000_u64 + (x.tv_usec as u64); } } diff --git a/doc/tutorial.md b/doc/tutorial.md index 41895ebed7c..909bad9e2f4 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -583,19 +583,16 @@ Inherited mutability means that any field of a struct may be mutable, if the struct is in a mutable slot (or a field of a struct in a mutable slot, and so forth). -A struct that is not mutable due to inherited mutability may declare some -of its fields nevertheless mutable, using the `mut` keyword. - ~~~~ struct Stack { content: ~[int], - mut head: uint + head: uint } ~~~~ -With a value of such a type, you can do `mystack.head += 1`. If `mut` were -omitted from the type, such an assignment to a struct without inherited -mutability would result in a type error. +With a value (say, `mystack`) of such a type in a mutable location, you can do +`mystack.head += 1`. But in an immutable location, such an assignment to a +struct without inherited mutability would result in a type error. `match` patterns destructure structs. The basic syntax is `Name { fieldname: pattern, ... }`: @@ -938,19 +935,19 @@ type that contains managed boxes or other managed types. ~~~ // A linked list node struct Node { - mut next: MaybeNode, - mut prev: MaybeNode, + next: MaybeNode, + prev: MaybeNode, payload: int } enum MaybeNode { - SomeNode(@Node), + SomeNode(@mut Node), NoNode } -let node1 = @Node { next: NoNode, prev: NoNode, payload: 1 }; -let node2 = @Node { next: NoNode, prev: NoNode, payload: 2 }; -let node3 = @Node { next: NoNode, prev: NoNode, payload: 3 }; +let node1 = @mut Node { next: NoNode, prev: NoNode, payload: 1 }; +let node2 = @mut Node { next: NoNode, prev: NoNode, payload: 2 }; +let node3 = @mut Node { next: NoNode, prev: NoNode, payload: 3 }; // Link the three list nodes together node1.next = SomeNode(node2); @@ -2300,8 +2297,8 @@ mod farm { # impl Human { fn rest(&self) { } } # pub fn make_me_a_farm() -> farm::Farm { farm::Farm { chickens: ~[], cows: ~[], farmer: Human(0) } } pub struct Farm { - priv mut chickens: ~[Chicken], - priv mut cows: ~[Cow], + priv chickens: ~[Chicken], + priv cows: ~[Cow], farmer: Human } |
