librustc: Remove ~EXPR, ~TYPE, and ~PAT from the language, except

for `~str`/`~[]`.

Note that `~self` still remains, since I forgot to add support for
`Box<self>` before the snapshot.

How to update your code:

* Instead of `~EXPR`, you should write `box EXPR`.

* Instead of `~TYPE`, you should write `Box<Type>`.

* Instead of `~PATTERN`, you should write `box PATTERN`.

[breaking-change]
This commit is contained in:
Patrick Walton 2014-05-05 18:56:44 -07:00
parent 24f6f26e63
commit 090040bf40
495 changed files with 2252 additions and 1897 deletions

View file

@ -293,7 +293,7 @@ extern {
fn main() {
// Create the object that will be referenced in the callback
let mut rust_object = ~RustObject{ a: 5 };
let mut rust_object = box RustObject { a: 5 };
unsafe {
register_callback(&mut *rust_object, callback);

View file

@ -41,9 +41,9 @@ point, but allocated in a different place:
~~~
# struct Point {x: f64, y: f64}
let on_the_stack : Point = Point {x: 3.0, y: 4.0};
let managed_box : @Point = @Point {x: 5.0, y: 1.0};
let owned_box : ~Point = ~Point {x: 7.0, y: 9.0};
let on_the_stack : Point = Point {x: 3.0, y: 4.0};
let managed_box : @Point = @Point {x: 5.0, y: 1.0};
let owned_box : Box<Point> = box Point {x: 7.0, y: 9.0};
~~~
Suppose we wanted to write a procedure that computed the distance between any
@ -72,9 +72,9 @@ Now we can call `compute_distance()` in various ways:
~~~
# struct Point {x: f64, y: f64}
# let on_the_stack : Point = Point{x: 3.0, y: 4.0};
# let managed_box : @Point = @Point{x: 5.0, y: 1.0};
# let owned_box : ~Point = ~Point{x: 7.0, y: 9.0};
# let on_the_stack : Point = Point{x: 3.0, y: 4.0};
# let managed_box : @Point = @Point{x: 5.0, y: 1.0};
# let owned_box : Box<Point> = box Point{x: 7.0, y: 9.0};
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
compute_distance(&on_the_stack, managed_box);
compute_distance(managed_box, owned_box);
@ -151,12 +151,12 @@ Now, as before, we can define rectangles in a few different ways:
# struct Point {x: f64, y: f64}
# struct Size {w: f64, h: f64} // as before
# struct Rectangle {origin: Point, size: Size}
let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0},
size: Size {w: 3.0, h: 4.0}};
let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0},
size: Size {w: 3.0, h: 4.0}};
let rect_owned = ~Rectangle {origin: Point {x: 5.0, y: 6.0},
size: Size {w: 3.0, h: 4.0}};
let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0},
size: Size {w: 3.0, h: 4.0}};
let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0},
size: Size {w: 3.0, h: 4.0}};
let rect_owned = box Rectangle {origin: Point {x: 5.0, y: 6.0},
size: Size {w: 3.0, h: 4.0}};
~~~
In each case, we can extract out individual subcomponents with the `&`
@ -168,7 +168,7 @@ operator. For example, I could write:
# struct Rectangle {origin: Point, size: Size}
# let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0}, size: Size {w: 3.0, h: 4.0}};
# let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0}, size: Size {w: 3.0, h: 4.0}};
# let rect_owned = ~Rectangle {origin: Point {x: 5.0, y: 6.0}, size: Size {w: 3.0, h: 4.0}};
# let rect_owned = box Rectangle {origin: Point {x: 5.0, y: 6.0}, size: Size {w: 3.0, h: 4.0}};
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
compute_distance(&rect_stack.origin, &rect_managed.origin);
~~~
@ -276,12 +276,12 @@ the following function is legal:
# fn some_condition() -> bool { true }
# struct Foo { f: int }
fn example3() -> int {
let mut x = ~Foo {f: 3};
let mut x = box Foo {f: 3};
if some_condition() {
let y = &x.f; // -+ L
return *y; // |
} // -+
x = ~Foo {f: 4};
x = box Foo {f: 4};
// ...
# return 0;
}
@ -301,9 +301,9 @@ rejected by the compiler):
~~~ {.ignore}
fn example3() -> int {
let mut x = ~X {f: 3};
let mut x = box X {f: 3};
let y = &x.f;
x = ~X {f: 4}; // Error reported here.
x = box X {f: 4}; // Error reported here.
*y
}
~~~
@ -314,13 +314,13 @@ memory immediately before the re-assignment of `x`:
~~~ {.notrust}
Stack Exchange Heap
x +----------+
| ~{f:int} | ----+
y +----------+ |
| &int | ----+
+----------+ | +---------+
+--> | f: 3 |
+---------+
x +-------------+
| box {f:int} | ----+
y +-------------+ |
| &int | ----+
+-------------+ | +---------+
+--> | f: 3 |
+---------+
~~~
Once the reassignment occurs, the memory will look like this:
@ -328,13 +328,13 @@ Once the reassignment occurs, the memory will look like this:
~~~ {.notrust}
Stack Exchange Heap
x +----------+ +---------+
| ~{f:int} | -------> | f: 4 |
y +----------+ +---------+
| &int | ----+
+----------+ | +---------+
+--> | (freed) |
+---------+
x +-------------+ +---------+
| box {f:int} | -------> | f: 4 |
y +-------------+ +---------+
| &int | ----+
+-------------+ | +---------+
+--> | (freed) |
+---------+
~~~
Here you can see that the variable `y` still points at the old box,
@ -349,12 +349,12 @@ mutations:
~~~ {.ignore}
fn example3() -> int {
struct R { g: int }
struct S { f: ~R }
struct S { f: Box<R> }
let mut x = ~S {f: ~R {g: 3}};
let mut x = box S {f: box R {g: 3}};
let y = &x.f.g;
x = ~S {f: ~R {g: 4}}; // Error reported here.
x.f = ~R {g: 5}; // Error reported here.
x = box S {f: box R {g: 4}}; // Error reported here.
x.f = box R {g: 5}; // Error reported here.
*y
}
~~~

View file

@ -182,13 +182,14 @@ trait. Therefore, unboxed traits don't make any sense, and aren't allowed.
Sometimes, you need a recursive data structure. The simplest is known as a 'cons list':
~~~rust
enum List<T> {
Nil,
Cons(T, ~List<T>),
Cons(T, Box<List<T>>),
}
fn main() {
let list: List<int> = Cons(1, ~Cons(2, ~Cons(3, ~Nil)));
let list: List<int> = Cons(1, box Cons(2, box Cons(3, box Nil)));
println!("{:?}", list);
}
~~~
@ -196,7 +197,7 @@ fn main() {
This prints:
~~~ {.notrust}
Cons(1, ~Cons(2, ~Cons(3, ~Nil)))
Cons(1, box Cons(2, box Cons(3, box Nil)))
~~~
The inner lists _must_ be an owned pointer, because we can't know how many
@ -237,7 +238,7 @@ struct Point {
}
fn main() {
let a = ~Point { x: 10, y: 20 };
let a = box Point { x: 10, y: 20 };
spawn(proc() {
println!("{}", a.x);
});
@ -268,7 +269,7 @@ struct Point {
}
fn main() {
let a = ~Point { x: 10, y: 20 };
let a = box Point { x: 10, y: 20 };
let b = a;
println!("{}", b.x);
println!("{}", a.x);
@ -285,7 +286,7 @@ note: in expansion of format_args!
<std-macros>:158:27: 158:81 note: expansion site
<std-macros>:157:5: 159:6 note: in expansion of println!
test.rs:10:5: 10:25 note: expansion site
test.rs:8:9: 8:10 note: `a` moved here because it has type `~Point`, which is moved by default (use `ref` to override)
test.rs:8:9: 8:10 note: `a` moved here because it has type `Box<Point>`, which is moved by default (use `ref` to override)
test.rs:8 let b = a;
^
~~~
@ -345,8 +346,8 @@ fn compute_distance(p1: &Point, p2: &Point) -> f32 {
}
fn main() {
let origin = @Point { x: 0.0, y: 0.0 };
let p1 = ~Point { x: 5.0, y: 3.0 };
let origin = @Point { x: 0.0, y: 0.0 };
let p1 = box Point { x: 5.0, y: 3.0 };
println!("{:?}", compute_distance(origin, p1));
}
@ -381,7 +382,7 @@ duration a 'lifetime'. Let's try a more complex example:
~~~rust
fn main() {
let mut x = ~5;
let mut x = box 5;
if *x < 10 {
let y = &x;
println!("Oh no: {:?}", y);
@ -398,7 +399,7 @@ mutated, and therefore, lets us pass. This wouldn't work:
~~~rust{.ignore}
fn main() {
let mut x = ~5;
let mut x = box 5;
if *x < 10 {
let y = &x;
*x -= 1;
@ -437,12 +438,12 @@ is best.
What does that mean? Don't do this:
~~~rust
fn foo(x: ~int) -> ~int {
return ~*x;
fn foo(x: Box<int>) -> Box<int> {
return box *x;
}
fn main() {
let x = ~5;
let x = box 5;
let y = foo(x);
}
~~~
@ -450,13 +451,13 @@ fn main() {
Do this:
~~~rust
fn foo(x: ~int) -> int {
fn foo(x: Box<int>) -> int {
return *x;
}
fn main() {
let x = ~5;
let y = ~foo(x);
let x = box 5;
let y = box foo(x);
}
~~~
@ -464,12 +465,12 @@ This gives you flexibility, without sacrificing performance. For example, this w
also work:
~~~rust
fn foo(x: ~int) -> int {
fn foo(x: Box<int>) -> int {
return *x;
}
fn main() {
let x = ~5;
let x = box 5;
let y = @foo(x);
}
~~~

View file

@ -258,10 +258,10 @@ impl<T: Send> Drop for Unique<T> {
}
}
// A comparison between the built-in ~ and this reimplementation
// A comparison between the built-in `Box` and this reimplementation
fn main() {
{
let mut x = ~5;
let mut x = box 5;
*x = 10;
} // `x` is freed here

View file

@ -127,12 +127,13 @@ That's a great example for stack memory,
but what about heap memory?
Rust has a second kind of pointer,
an 'owned box',
that you can create with a `~`.
that you can create with the `box` operator.
Check it out:
```
fn dangling() -> ~int {
let i = ~1234;
fn dangling() -> Box<int> {
let i = box 1234;
return i;
}
@ -143,7 +144,7 @@ fn add_one() -> int {
```
Now instead of a stack allocated `1234`,
we have a heap allocated `~1234`.
we have a heap allocated `box 1234`.
Whereas `&` borrows a pointer to existing memory,
creating an owned box allocates memory on the heap and places a value in it,
giving you the sole pointer to that memory.
@ -151,7 +152,7 @@ You can roughly compare these two lines:
```
// Rust
let i = ~1234;
let i = box 1234;
```
```notrust

View file

@ -1393,7 +1393,7 @@ to pointers to the trait name, used as a type.
# trait Shape { }
# impl Shape for int { }
# let mycircle = 0;
let myshape: ~Shape = ~mycircle as ~Shape;
let myshape: Box<Shape> = box mycircle as Box<Shape>;
~~~~
The resulting value is a managed box containing the value that was cast,
@ -3041,19 +3041,19 @@ stands for a *single* data field, whereas a wildcard `..` stands for *all* the
fields of a particular variant. For example:
~~~~
enum List<X> { Nil, Cons(X, ~List<X>) }
enum List<X> { Nil, Cons(X, Box<List<X>>) }
let x: List<int> = Cons(10, ~Cons(11, ~Nil));
let x: List<int> = Cons(10, box Cons(11, box Nil));
match x {
Cons(_, ~Nil) => fail!("singleton list"),
Cons(..) => return,
Nil => fail!("empty list")
Cons(_, box Nil) => fail!("singleton list"),
Cons(..) => return,
Nil => fail!("empty list")
}
~~~~
The first pattern matches lists constructed by applying `Cons` to any head
value, and a tail value of `~Nil`. The second pattern matches _any_ list
value, and a tail value of `box Nil`. The second pattern matches _any_ list
constructed with `Cons`, ignoring the values of its arguments. The difference
between `_` and `..` is that the pattern `C(_)` is only type-correct if `C` has
exactly one argument, while the pattern `C(..)` is type-correct for any enum
@ -3103,12 +3103,12 @@ An example of a `match` expression:
# fn process_pair(a: int, b: int) { }
# fn process_ten() { }
enum List<X> { Nil, Cons(X, ~List<X>) }
enum List<X> { Nil, Cons(X, Box<List<X>>) }
let x: List<int> = Cons(10, ~Cons(11, ~Nil));
let x: List<int> = Cons(10, box Cons(11, box Nil));
match x {
Cons(a, ~Cons(b, _)) => {
Cons(a, box Cons(b, _)) => {
process_pair(a,b);
}
Cons(10, _) => {
@ -3135,17 +3135,17 @@ Subpatterns can also be bound to variables by the use of the syntax
For example:
~~~~
enum List { Nil, Cons(uint, ~List) }
enum List { Nil, Cons(uint, Box<List>) }
fn is_sorted(list: &List) -> bool {
match *list {
Nil | Cons(_, ~Nil) => true,
Cons(x, ref r @ ~Cons(y, _)) => (x <= y) && is_sorted(*r)
Nil | Cons(_, box Nil) => true,
Cons(x, ref r @ box Cons(y, _)) => (x <= y) && is_sorted(*r)
}
}
fn main() {
let a = Cons(6, ~Cons(7, ~Cons(42, ~Nil)));
let a = Cons(6, box Cons(7, box Cons(42, box Nil)));
assert!(is_sorted(&a));
}
@ -3411,10 +3411,10 @@ An example of a *recursive* type and its use:
~~~~
enum List<T> {
Nil,
Cons(T, ~List<T>)
Cons(T, Box<List<T>>)
}
let a: List<int> = Cons(7, ~Cons(13, ~Nil));
let a: List<int> = Cons(7, box Cons(13, box Nil));
~~~~
### Pointer types
@ -3563,12 +3563,12 @@ impl Printable for int {
fn to_string(&self) -> ~str { self.to_str() }
}
fn print(a: ~Printable) {
fn print(a: Box<Printable>) {
println!("{}", a.to_string());
}
fn main() {
print(~10 as ~Printable);
print(box 10 as Box<Printable>);
}
~~~~
@ -3755,7 +3755,7 @@ mutable slot by prefixing them with `mut` (similar to regular arguments):
~~~
trait Changer {
fn change(mut self) -> Self;
fn modify(mut ~self) -> ~Self;
fn modify(mut ~self) -> Box<Self>;
}
~~~
@ -3768,12 +3768,14 @@ initialized; this is enforced by the compiler.
### Owned boxes
An _owned box_ is a reference to a heap allocation holding another value, which is constructed
by the prefix *tilde* sigil `~`.
by the prefix operator `box`. When the standard library is in use, the type of an owned box is
`std::owned::Box<T>`.
An example of an owned box type and value:
~~~~
let x: ~int = ~10;
let x: Box<int> = box 10;
~~~~
Owned box values exist in 1:1 correspondence with their heap allocation
@ -3781,7 +3783,7 @@ copying an owned box value makes a shallow copy of the pointer
Rust will consider a shallow copy of an owned box to move ownership of the value. After a value has been moved, the source location cannot be used unless it is reinitialized.
~~~~
let x: ~int = ~10;
let x: Box<int> = box 10;
let y = x;
// attempting to use `x` will result in an error here
~~~~

View file

@ -911,12 +911,12 @@ Objects are never accessible after their destructor has been called, so no
dynamic failures are possible from accessing freed resources. When a task
fails, destructors of all objects in the task are called.
The `~` sigil represents a unique handle for a memory allocation on the heap:
The `box` operator performs memory allocation on the heap:
~~~~
{
// an integer allocated on the heap
let y = ~10;
let y = box 10;
}
// the destructor frees the heap memory as soon as `y` goes out of scope
~~~~
@ -938,17 +938,17 @@ and destroy the contained object when they go out of scope.
~~~~
// the struct owns the objects contained in the `x` and `y` fields
struct Foo { x: int, y: ~int }
struct Foo { x: int, y: Box<int> }
{
// `a` is the owner of the struct, and thus the owner of the struct's fields
let a = Foo { x: 5, y: ~10 };
let a = Foo { x: 5, y: box 10 };
}
// when `a` goes out of scope, the destructor for the `~int` in the struct's
// field is called
// `b` is mutable, and the mutability is inherited by the objects it owns
let mut b = Foo { x: 5, y: ~10 };
let mut b = Foo { x: 5, y: box 10 };
b.x = 10;
~~~~
@ -1021,13 +1021,15 @@ Our previous attempt at defining the `List` type included an `u32` and a `List`
directly inside `Cons`, making it at least as big as the sum of both types. The
type was invalid because the size was infinite!
An *owned box* (`~`) uses a dynamic memory allocation to provide the invariant
of always being the size of a pointer, regardless of the contained type. This
can be leveraged to create a valid `List` definition:
An *owned box* (`Box`, located in the `std::owned` module) uses a dynamic memory
allocation to provide the invariant of always being the size of a pointer,
regardless of the contained type. This can be leveraged to create a valid `List`
definition:
~~~
enum List {
Cons(u32, ~List),
Cons(u32, Box<List>),
Nil
}
~~~
@ -1040,10 +1042,10 @@ Consider an instance of our `List` type:
~~~
# enum List {
# Cons(u32, ~List),
# Cons(u32, Box<List>),
# Nil
# }
let list = Cons(1, ~Cons(2, ~Cons(3, ~Nil)));
let list = Cons(1, box Cons(2, box Cons(3, box Nil)));
~~~
It represents an owned tree of values, inheriting mutability down the tree and
@ -1054,7 +1056,7 @@ box, while the owner holds onto a pointer to it:
~~~ {.notrust}
List box List box List box List box
+--------------+ +--------------+ +--------------+ +----------+
list -> | Cons | 1 | ~ | -> | Cons | 2 | ~ | -> | Cons | 3 | ~ | -> | Nil |
list -> | Cons | 1 | | -> | Cons | 2 | | -> | Cons | 3 | | -> | Nil |
+--------------+ +--------------+ +--------------+ +----------+
~~~
@ -1074,10 +1076,10 @@ the box rather than doing an implicit heap allocation.
~~~
# enum List {
# Cons(u32, ~List),
# Cons(u32, Box<List>),
# Nil
# }
let xs = Cons(1, ~Cons(2, ~Cons(3, ~Nil)));
let xs = Cons(1, box Cons(2, box Cons(3, box Nil)));
let ys = xs; // copies `Cons(u32, pointer)` shallowly
~~~
@ -1087,7 +1089,7 @@ location cannot be used unless it is reinitialized.
~~~
# enum List {
# Cons(u32, ~List),
# Cons(u32, Box<List>),
# Nil
# }
let mut xs = Nil;
@ -1107,7 +1109,7 @@ as it is only called a single time.
Avoiding a move can be done with the library-defined `clone` method:
~~~~
let x = ~5;
let x = box 5;
let y = x.clone(); // `y` is a newly allocated box
let z = x; // no new memory allocated, `x` can no longer be used
~~~~
@ -1118,11 +1120,11 @@ our `List` type. Traits will be explained in detail [later](#traits).
~~~{.ignore}
#[deriving(Clone)]
enum List {
Cons(u32, ~List),
Cons(u32, Box<List>),
Nil
}
let x = Cons(5, ~Nil);
let x = Cons(5, box Nil);
let y = x.clone();
// `x` can still be used!
@ -1135,7 +1137,7 @@ let z = x;
The mutability of a value may be changed by moving it to a new owner:
~~~~
let r = ~13;
let r = box 13;
let mut s = r; // box becomes mutable
*s += 1;
let t = s; // box becomes immutable
@ -1146,12 +1148,12 @@ advantage of moves:
~~~
enum List {
Cons(u32, ~List),
Cons(u32, Box<List>),
Nil
}
fn prepend(xs: List, value: u32) -> List {
Cons(value, ~xs)
Cons(value, box xs)
}
let mut xs = Nil;
@ -1186,7 +1188,7 @@ by-value. A recursive definition of equality using references is as follows:
~~~
# enum List {
# Cons(u32, ~List),
# Cons(u32, Box<List>),
# Nil
# }
fn eq(xs: &List, ys: &List) -> bool {
@ -1195,15 +1197,15 @@ fn eq(xs: &List, ys: &List) -> bool {
// If we have reached the end of both lists, they are equal.
(&Nil, &Nil) => true,
// If the current elements of both lists are equal, keep going.
(&Cons(x, ~ref next_xs), &Cons(y, ~ref next_ys))
(&Cons(x, box ref next_xs), &Cons(y, box ref next_ys))
if x == y => eq(next_xs, next_ys),
// If the current elements are not equal, the lists are not equal.
_ => false
}
}
let xs = Cons(5, ~Cons(10, ~Nil));
let ys = Cons(5, ~Cons(10, ~Nil));
let xs = Cons(5, box Cons(10, box Nil));
let ys = Cons(5, box Cons(10, box Nil));
assert!(eq(&xs, &ys));
~~~
@ -1223,7 +1225,7 @@ The `u32` in the previous definition can be substituted with a type parameter:
~~~
enum List<T> {
Cons(T, ~List<T>),
Cons(T, Box<List<T>>),
Nil
}
~~~
@ -1233,11 +1235,11 @@ definition has to be updated too:
~~~
# enum List<T> {
# Cons(T, ~List<T>),
# Cons(T, Box<List<T>>),
# Nil
# }
fn prepend<T>(xs: List<T>, value: T) -> List<T> {
Cons(value, ~xs)
Cons(value, box xs)
}
~~~
@ -1248,11 +1250,11 @@ Using the generic `List<T>` works much like before, thanks to type inference:
~~~
# enum List<T> {
# Cons(T, ~List<T>),
# Cons(T, Box<List<T>>),
# Nil
# }
# fn prepend<T>(xs: List<T>, value: T) -> List<T> {
# Cons(value, ~xs)
# Cons(value, box xs)
# }
let mut xs = Nil; // Unknown type! This is a `List<T>`, but `T` can be anything.
xs = prepend(xs, 10); // Here the compiler infers `xs`'s type as `List<int>`.
@ -1265,11 +1267,11 @@ equivalent to the following type-annotated code:
~~~
# enum List<T> {
# Cons(T, ~List<T>),
# Cons(T, Box<List<T>>),
# Nil
# }
# fn prepend<T>(xs: List<T>, value: T) -> List<T> {
# Cons(value, ~xs)
# Cons(value, box xs)
# }
let mut xs: List<int> = Nil::<int>;
xs = prepend::<int>(xs, 10);
@ -1293,7 +1295,7 @@ Two more `ref` annotations need to be added to avoid attempting to move out the
~~~
# enum List<T> {
# Cons(T, ~List<T>),
# Cons(T, Box<List<T>>),
# Nil
# }
fn eq<T: Eq>(xs: &List<T>, ys: &List<T>) -> bool {
@ -1302,15 +1304,15 @@ fn eq<T: Eq>(xs: &List<T>, ys: &List<T>) -> bool {
// If we have reached the end of both lists, they are equal.
(&Nil, &Nil) => true,
// If the current elements of both lists are equal, keep going.
(&Cons(ref x, ~ref next_xs), &Cons(ref y, ~ref next_ys))
(&Cons(ref x, box ref next_xs), &Cons(ref y, box ref next_ys))
if x == y => eq(next_xs, next_ys),
// If the current elements are not equal, the lists are not equal.
_ => false
}
}
let xs = Cons('c', ~Cons('a', ~Cons('t', ~Nil)));
let ys = Cons('c', ~Cons('a', ~Cons('t', ~Nil)));
let xs = Cons('c', box Cons('a', box Cons('t', box Nil)));
let ys = Cons('c', box Cons('a', box Cons('t', box Nil)));
assert!(eq(&xs, &ys));
~~~
@ -1321,7 +1323,7 @@ on.
~~~
# enum List<T> {
# Cons(T, ~List<T>),
# Cons(T, Box<List<T>>),
# Nil
# }
impl<T: Eq> Eq for List<T> {
@ -1331,7 +1333,7 @@ impl<T: Eq> Eq for List<T> {
// If we have reached the end of both lists, they are equal.
(&Nil, &Nil) => true,
// If the current elements of both lists are equal, keep going.
(&Cons(ref x, ~ref next_xs), &Cons(ref y, ~ref next_ys))
(&Cons(ref x, box ref next_xs), &Cons(ref y, box ref next_ys))
if x == y => next_xs == next_ys,
// If the current elements are not equal, the lists are not equal.
_ => false
@ -1339,8 +1341,8 @@ impl<T: Eq> Eq for List<T> {
}
}
let xs = Cons(5, ~Cons(10, ~Nil));
let ys = Cons(5, ~Cons(10, ~Nil));
let xs = Cons(5, box Cons(10, box Nil));
let ys = Cons(5, box Cons(10, box Nil));
// The methods below are part of the Eq trait,
// which we implemented on our linked list.
assert!(xs.eq(&ys));
@ -1373,7 +1375,7 @@ fn foo() -> (u64, u64, u64, u64, u64, u64) {
(5, 5, 5, 5, 5, 5)
}
let x = ~foo(); // allocates a `~` box, and writes the integers directly to it
let x = box foo(); // allocates a box, and writes the integers directly to it
~~~~
Beyond the properties granted by the size, an owned box behaves as a regular
@ -1384,8 +1386,8 @@ let x = 5; // immutable
let mut y = 5; // mutable
y += 2;
let x = ~5; // immutable
let mut y = ~5; // mutable
let x = box 5; // immutable
let mut y = box 5; // mutable
*y += 2; // the `*` operator is needed to access the contained value
~~~~
@ -1413,8 +1415,8 @@ contains a point, but allocated in a different location:
~~~
# struct Point { x: f64, y: f64 }
let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 };
let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
let owned_box : Box<Point> = box Point { x: 7.0, y: 9.0 };
~~~
Suppose we want to write a procedure that computes the distance
@ -1438,8 +1440,8 @@ Now we can call `compute_distance()` in various ways:
~~~
# struct Point{ x: f64, y: f64 };
# let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
# let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 };
# let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
# let owned_box : Box<Point> = box Point { x: 7.0, y: 9.0 };
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
compute_distance(&on_the_stack, owned_box);
~~~
@ -1453,7 +1455,7 @@ route to the same data.
In the case of `owned_box`, however, no
explicit action is necessary. The compiler will automatically convert
a box `~point` to a reference like
a box `box point` to a reference like
`&point`. This is another form of borrowing; in this case, the
contents of the owned box are being lent out.
@ -1492,7 +1494,7 @@ Rust uses the unary star operator (`*`) to access the contents of a
box or pointer, similarly to C.
~~~
let owned = ~10;
let owned = box 10;
let borrowed = &20;
let sum = *owned + *borrowed;
@ -1503,7 +1505,7 @@ assignments. Such an assignment modifies the value that the pointer
points to.
~~~
let mut owned = ~10;
let mut owned = box 10;
let mut value = 20;
let borrowed = &mut value;
@ -1520,8 +1522,8 @@ can sometimes make code awkward and parenthesis-filled.
# struct Point { x: f64, y: f64 }
# enum Shape { Rectangle(Point, Point) }
# impl Shape { fn area(&self) -> int { 0 } }
let start = ~Point { x: 10.0, y: 20.0 };
let end = ~Point { x: (*start).x + 100.0, y: (*start).y + 100.0 };
let start = box Point { x: 10.0, y: 20.0 };
let end = box Point { x: (*start).x + 100.0, y: (*start).y + 100.0 };
let rect = &Rectangle(*start, *end);
let area = (*rect).area();
~~~
@ -1534,8 +1536,8 @@ dot), so in most cases, explicitly dereferencing the receiver is not necessary.
# struct Point { x: f64, y: f64 }
# enum Shape { Rectangle(Point, Point) }
# impl Shape { fn area(&self) -> int { 0 } }
let start = ~Point { x: 10.0, y: 20.0 };
let end = ~Point { x: start.x + 100.0, y: start.y + 100.0 };
let start = box Point { x: 10.0, y: 20.0 };
let end = box Point { x: start.x + 100.0, y: start.y + 100.0 };
let rect = &Rectangle(*start, *end);
let area = rect.area();
~~~
@ -1546,7 +1548,7 @@ something silly like
~~~
# struct Point { x: f64, y: f64 }
let point = &~Point { x: 10.0, y: 20.0 };
let point = &box Point { x: 10.0, y: 20.0 };
println!("{:f}", point.x);
~~~
@ -1944,7 +1946,7 @@ impl Shape {
let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
(&s).draw_reference();
(~s).draw_owned();
(box s).draw_owned();
s.draw_value();
~~~
@ -1969,7 +1971,7 @@ to a reference.
// As with typical function arguments, owned pointers
// are automatically converted to references
(~s).draw_reference();
(box s).draw_reference();
// Unlike typical function arguments, the self value will
// automatically be referenced ...
@ -1979,7 +1981,7 @@ s.draw_reference();
(& &s).draw_reference();
// ... and dereferenced and borrowed
(&~s).draw_reference();
(&box s).draw_reference();
~~~
Implementations may also define standalone (sometimes called "static")
@ -2433,7 +2435,7 @@ an _object_.
~~~~
# trait Drawable { fn draw(&self); }
fn draw_all(shapes: &[~Drawable]) {
fn draw_all(shapes: &[Box<Drawable>]) {
for shape in shapes.iter() { shape.draw(); }
}
~~~~
@ -2448,14 +2450,14 @@ to an object:
# trait Drawable { fn draw(&self); }
# fn new_circle() -> Circle { 1 }
# fn new_rectangle() -> Rectangle { true }
# fn draw_all(shapes: &[~Drawable]) {}
# fn draw_all(shapes: &[Box<Drawable>]) {}
impl Drawable for Circle { fn draw(&self) { /* ... */ } }
impl Drawable for Rectangle { fn draw(&self) { /* ... */ } }
let c: ~Circle = ~new_circle();
let r: ~Rectangle = ~new_rectangle();
draw_all([c as ~Drawable, r as ~Drawable]);
let c: Box<Circle> = box new_circle();
let r: Box<Rectangle> = box new_rectangle();
draw_all([c as Box<Drawable>, r as Box<Drawable>]);
~~~~
We omit the code for `new_circle` and `new_rectangle`; imagine that
@ -2464,7 +2466,7 @@ that, like strings and vectors, objects have dynamic size and may
only be referred to via one of the pointer types.
Other pointer types work as well.
Casts to traits may only be done with compatible pointers so,
for example, an `&Circle` may not be cast to an `~Drawable`.
for example, an `&Circle` may not be cast to a `Box<Drawable>`.
~~~
# type Circle = int; type Rectangle = int;
@ -2473,7 +2475,7 @@ for example, an `&Circle` may not be cast to an `~Drawable`.
# fn new_circle() -> int { 1 }
# fn new_rectangle() -> int { 2 }
// An owned object
let owny: ~Drawable = ~new_circle() as ~Drawable;
let owny: Box<Drawable> = box new_circle() as Box<Drawable>;
// A borrowed object
let stacky: &Drawable = &new_circle() as &Drawable;
~~~
@ -2497,7 +2499,7 @@ valid types:
trait Foo {}
trait Bar<T> {}
fn sendable_foo(f: ~Foo:Send) { /* ... */ }
fn sendable_foo(f: Box<Foo:Send>) { /* ... */ }
fn shareable_bar<T: Share>(b: &Bar<T>: Share) { /* ... */ }
~~~