@@ -348,12 +348,12 @@ mutations:
348
348
~~~ {.xfail-test}
349
349
fn example3() -> int {
350
350
struct R { g: int }
351
- struct S { mut f: ~R }
351
+ struct S { f: ~R }
352
352
353
- let mut x = ~S {mut f: ~R {g: 3}};
353
+ let mut x = ~S {f: ~R {g: 3}};
354
354
let y = &x.f.g;
355
- x = ~S {mut f: ~R {g: 4}}; // Error reported here.
356
- x.f = ~R {g: 5}; // Error reported here.
355
+ x = ~S {f: ~R {g: 4}}; // Error reported here.
356
+ x.f = ~R {g: 5}; // Error reported here.
357
357
*y
358
358
}
359
359
~~~
@@ -362,91 +362,6 @@ In this case, two errors are reported, one when the variable `x` is
362
362
modified and another when ` x.f ` is modified. Either modification would
363
363
invalidate the pointer ` y ` .
364
364
365
- Things get trickier when the unique box is not uniquely owned by the
366
- stack frame, or when there is no way for the compiler to determine the
367
- box's owner. Consider a program like this:
368
-
369
- ~~~ {.xfail-test}
370
- struct R { g: int }
371
- struct S { mut f: ~R }
372
- fn example5a(x: @S, callback: @fn()) -> int {
373
- let y = &x.f.g; // Error reported here.
374
- ...
375
- callback();
376
- ...
377
- # return 0;
378
- }
379
- ~~~
380
-
381
- Here the heap looks something like:
382
-
383
- ~~~ {.notrust}
384
- Stack Managed Heap Exchange Heap
385
-
386
- x +------+ +-------------+ +------+
387
- | @... | ----> | mut f: ~... | --+-> | g: 3 |
388
- y +------+ +-------------+ | +------+
389
- | &int | -------------------------+
390
- +------+
391
- ~~~
392
-
393
- In this case, the owning reference to the value being borrowed is
394
- ` x.f ` . Moreover, ` x.f ` is both mutable and * aliasable* . Aliasable
395
- means that there may be other pointers to that same managed box, so
396
- even if the compiler were to prove an absence of mutations to ` x.f ` ,
397
- code could mutate ` x.f ` indirectly by changing an alias of
398
- ` x ` . Therefore, to be safe, the compiler only accepts * pure* actions
399
- during the lifetime of ` y ` . We define what "pure" means in the section
400
- on [ purity] ( #purity ) .
401
-
402
- Besides ensuring purity, the only way to borrow the interior of a
403
- unique found in aliasable memory is to ensure that the borrowed field
404
- itself is also unique, as in the following example:
405
-
406
- ~~~
407
- struct R { g: int }
408
- struct S { f: ~R }
409
- fn example5b(x: @S) -> int {
410
- let y = &x.f.g;
411
- ...
412
- # return 0;
413
- }
414
- ~~~
415
-
416
- Here, the field ` f ` is not declared as mutable. But that is enough for
417
- the compiler to know that, even if aliases to ` x ` exist, the field ` f `
418
- cannot be changed and hence the unique box ` g ` will remain valid.
419
-
420
- If you do have a unique box in a mutable field, and you wish to borrow
421
- it, one option is to use the swap operator to move that unique box
422
- onto your stack:
423
-
424
- ~~~
425
- struct R { g: int }
426
- struct S { mut f: ~R }
427
- fn example5c(x: @S) -> int {
428
- let mut v = ~R {g: 0};
429
- v <-> x.f; // Swap v and x.f
430
- { // Block constrains the scope of `y`:
431
- let y = &v.g;
432
- ...
433
- }
434
- x.f = v; // Replace x.f
435
- ...
436
- # return 0;
437
- }
438
- ~~~
439
-
440
- Of course, this has the side effect of modifying your managed box for
441
- the duration of the borrow, so it only works when you know that you
442
- won't be accessing that same box for the duration of the loan. Also,
443
- it is sometimes necessary to introduce additional blocks to constrain
444
- the scope of the loan. In this example, the borrowed pointer ` y `
445
- would still be in scope when you moved the value ` v ` back into ` x.f ` ,
446
- and hence moving ` v ` would be considered illegal. You cannot move
447
- values if they are the targets of valid outstanding loans. Introducing
448
- the block restricts the scope of ` y ` , making the move legal.
449
-
450
365
# Borrowing and enums
451
366
452
367
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
558
473
data are mutable, but otherwise it requires that the data reside in
559
474
immutable memory.
560
475
561
- > *** Note:*** Right now, pattern bindings not explicitly annotated
562
- > with ` ref ` or ` copy ` use a special mode of "implicit by reference".
563
- > This is changing as soon as we finish updating all the existing code
564
- > in the compiler that relies on the current settings.
565
-
566
476
# Returning borrowed pointers
567
477
568
478
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,
745
655
746
656
This is equivalent to the previous definition.
747
657
748
- # Purity
749
-
750
- As mentioned before, the Rust compiler offers a kind of escape hatch
751
- that permits borrowing of any data, as long as the actions that occur
752
- during the lifetime of the borrow are pure. Pure actions are those
753
- that only modify data owned by the current stack frame. The compiler
754
- can therefore permit arbitrary pointers into the heap, secure in the
755
- knowledge that no pure action will ever cause them to become
756
- invalidated (the compiler must still track data on the stack which is
757
- borrowed and enforce those rules normally, of course). A pure function
758
- in Rust is referentially transparent: it returns the same results
759
- given the same (observably equivalent) inputs. That is because while
760
- pure functions are allowed to modify data, they may only modify
761
- * stack-local* data, which cannot be observed outside the scope of the
762
- function itself. (Using an ` unsafe ` block invalidates this guarantee.)
763
-
764
- Let’s revisit a previous example and show how purity can affect
765
- typechecking. Here is ` example5a() ` , which borrows the interior of a
766
- unique box found in an aliasable, mutable location, only now we’ve
767
- replaced the ` ... ` with some specific code:
768
-
769
- ~~~
770
- struct R { g: int }
771
- struct S { mut f: ~R }
772
- fn example5a(x: @S ...) -> int {
773
- let y = &x.f.g; // Unsafe
774
- *y + 1
775
- }
776
- ~~~
777
-
778
- The new code simply returns an incremented version of ` y ` . This code
779
- clearly doesn't mutate the heap, so the compiler is satisfied.
780
-
781
- But suppose we wanted to pull the increment code into a helper, like
782
- this:
783
-
784
- ~~~
785
- fn add_one(x: &int) -> int { *x + 1 }
786
- ~~~
787
-
788
- We can now update ` example5a() ` to use ` add_one() ` :
789
-
790
- ~~~
791
- # struct R { g: int }
792
- # struct S { mut f: ~R }
793
- # pure fn add_one(x: &int) -> int { *x + 1 }
794
- fn example5a(x: @S ...) -> int {
795
- let y = &x.f.g;
796
- add_one(y) // Error reported here
797
- }
798
- ~~~
799
-
800
- But now the compiler will report an error again. The reason is that it
801
- only considers one function at a time (like most typecheckers), and
802
- so it does not know that ` add_one() ` consists of pure code. We can
803
- help the compiler by labeling ` add_one() ` as pure:
804
-
805
- ~~~
806
- pure fn add_one(x: &int) -> int { *x + 1 }
807
- ~~~
808
-
809
- With this change, the modified version of ` example5a() ` will again compile.
810
-
811
658
# Conclusion
812
659
813
660
So there you have it: a (relatively) brief tour of the borrowed pointer
0 commit comments