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:
parent
24f6f26e63
commit
090040bf40
495 changed files with 2252 additions and 1897 deletions
|
@ -293,7 +293,7 @@ extern {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Create the object that will be referenced in the callback
|
// 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 {
|
unsafe {
|
||||||
register_callback(&mut *rust_object, callback);
|
register_callback(&mut *rust_object, callback);
|
||||||
|
|
|
@ -41,9 +41,9 @@ point, but allocated in a different place:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
# struct Point {x: f64, y: f64}
|
# struct Point {x: f64, y: f64}
|
||||||
let on_the_stack : Point = Point {x: 3.0, y: 4.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 managed_box : @Point = @Point {x: 5.0, y: 1.0};
|
||||||
let owned_box : ~Point = ~Point {x: 7.0, y: 9.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
|
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}
|
# struct Point {x: f64, y: f64}
|
||||||
# let on_the_stack : Point = Point{x: 3.0, y: 4.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 managed_box : @Point = @Point{x: 5.0, y: 1.0};
|
||||||
# let owned_box : ~Point = ~Point{x: 7.0, y: 9.0};
|
# let owned_box : Box<Point> = box Point{x: 7.0, y: 9.0};
|
||||||
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
|
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
|
||||||
compute_distance(&on_the_stack, managed_box);
|
compute_distance(&on_the_stack, managed_box);
|
||||||
compute_distance(managed_box, owned_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 Point {x: f64, y: f64}
|
||||||
# struct Size {w: f64, h: f64} // as before
|
# struct Size {w: f64, h: f64} // as before
|
||||||
# struct Rectangle {origin: Point, size: Size}
|
# struct Rectangle {origin: Point, size: Size}
|
||||||
let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0},
|
let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0},
|
||||||
size: Size {w: 3.0, h: 4.0}};
|
size: Size {w: 3.0, h: 4.0}};
|
||||||
let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0},
|
let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0},
|
||||||
size: Size {w: 3.0, h: 4.0}};
|
size: Size {w: 3.0, h: 4.0}};
|
||||||
let rect_owned = ~Rectangle {origin: Point {x: 5.0, y: 6.0},
|
let rect_owned = box Rectangle {origin: Point {x: 5.0, y: 6.0},
|
||||||
size: Size {w: 3.0, h: 4.0}};
|
size: Size {w: 3.0, h: 4.0}};
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
In each case, we can extract out individual subcomponents with the `&`
|
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}
|
# 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_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_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 }
|
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
|
||||||
compute_distance(&rect_stack.origin, &rect_managed.origin);
|
compute_distance(&rect_stack.origin, &rect_managed.origin);
|
||||||
~~~
|
~~~
|
||||||
|
@ -276,12 +276,12 @@ the following function is legal:
|
||||||
# fn some_condition() -> bool { true }
|
# fn some_condition() -> bool { true }
|
||||||
# struct Foo { f: int }
|
# struct Foo { f: int }
|
||||||
fn example3() -> int {
|
fn example3() -> int {
|
||||||
let mut x = ~Foo {f: 3};
|
let mut x = box Foo {f: 3};
|
||||||
if some_condition() {
|
if some_condition() {
|
||||||
let y = &x.f; // -+ L
|
let y = &x.f; // -+ L
|
||||||
return *y; // |
|
return *y; // |
|
||||||
} // -+
|
} // -+
|
||||||
x = ~Foo {f: 4};
|
x = box Foo {f: 4};
|
||||||
// ...
|
// ...
|
||||||
# return 0;
|
# return 0;
|
||||||
}
|
}
|
||||||
|
@ -301,9 +301,9 @@ rejected by the compiler):
|
||||||
|
|
||||||
~~~ {.ignore}
|
~~~ {.ignore}
|
||||||
fn example3() -> int {
|
fn example3() -> int {
|
||||||
let mut x = ~X {f: 3};
|
let mut x = box X {f: 3};
|
||||||
let y = &x.f;
|
let y = &x.f;
|
||||||
x = ~X {f: 4}; // Error reported here.
|
x = box X {f: 4}; // Error reported here.
|
||||||
*y
|
*y
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
@ -314,13 +314,13 @@ memory immediately before the re-assignment of `x`:
|
||||||
~~~ {.notrust}
|
~~~ {.notrust}
|
||||||
Stack Exchange Heap
|
Stack Exchange Heap
|
||||||
|
|
||||||
x +----------+
|
x +-------------+
|
||||||
| ~{f:int} | ----+
|
| box {f:int} | ----+
|
||||||
y +----------+ |
|
y +-------------+ |
|
||||||
| &int | ----+
|
| &int | ----+
|
||||||
+----------+ | +---------+
|
+-------------+ | +---------+
|
||||||
+--> | f: 3 |
|
+--> | f: 3 |
|
||||||
+---------+
|
+---------+
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Once the reassignment occurs, the memory will look like this:
|
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}
|
~~~ {.notrust}
|
||||||
Stack Exchange Heap
|
Stack Exchange Heap
|
||||||
|
|
||||||
x +----------+ +---------+
|
x +-------------+ +---------+
|
||||||
| ~{f:int} | -------> | f: 4 |
|
| box {f:int} | -------> | f: 4 |
|
||||||
y +----------+ +---------+
|
y +-------------+ +---------+
|
||||||
| &int | ----+
|
| &int | ----+
|
||||||
+----------+ | +---------+
|
+-------------+ | +---------+
|
||||||
+--> | (freed) |
|
+--> | (freed) |
|
||||||
+---------+
|
+---------+
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Here you can see that the variable `y` still points at the old box,
|
Here you can see that the variable `y` still points at the old box,
|
||||||
|
@ -349,12 +349,12 @@ mutations:
|
||||||
~~~ {.ignore}
|
~~~ {.ignore}
|
||||||
fn example3() -> int {
|
fn example3() -> int {
|
||||||
struct R { g: 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;
|
let y = &x.f.g;
|
||||||
x = ~S {f: ~R {g: 4}}; // Error reported here.
|
x = box S {f: box R {g: 4}}; // Error reported here.
|
||||||
x.f = ~R {g: 5}; // Error reported here.
|
x.f = box R {g: 5}; // Error reported here.
|
||||||
*y
|
*y
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
|
|
@ -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':
|
Sometimes, you need a recursive data structure. The simplest is known as a 'cons list':
|
||||||
|
|
||||||
~~~rust
|
~~~rust
|
||||||
|
|
||||||
enum List<T> {
|
enum List<T> {
|
||||||
Nil,
|
Nil,
|
||||||
Cons(T, ~List<T>),
|
Cons(T, Box<List<T>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
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);
|
println!("{:?}", list);
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
@ -196,7 +197,7 @@ fn main() {
|
||||||
This prints:
|
This prints:
|
||||||
|
|
||||||
~~~ {.notrust}
|
~~~ {.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
|
The inner lists _must_ be an owned pointer, because we can't know how many
|
||||||
|
@ -237,7 +238,7 @@ struct Point {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = ~Point { x: 10, y: 20 };
|
let a = box Point { x: 10, y: 20 };
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
println!("{}", a.x);
|
println!("{}", a.x);
|
||||||
});
|
});
|
||||||
|
@ -268,7 +269,7 @@ struct Point {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = ~Point { x: 10, y: 20 };
|
let a = box Point { x: 10, y: 20 };
|
||||||
let b = a;
|
let b = a;
|
||||||
println!("{}", b.x);
|
println!("{}", b.x);
|
||||||
println!("{}", a.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>:158:27: 158:81 note: expansion site
|
||||||
<std-macros>:157:5: 159:6 note: in expansion of println!
|
<std-macros>:157:5: 159:6 note: in expansion of println!
|
||||||
test.rs:10:5: 10:25 note: expansion site
|
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;
|
test.rs:8 let b = a;
|
||||||
^
|
^
|
||||||
~~~
|
~~~
|
||||||
|
@ -345,8 +346,8 @@ fn compute_distance(p1: &Point, p2: &Point) -> f32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let origin = @Point { x: 0.0, y: 0.0 };
|
let origin = @Point { x: 0.0, y: 0.0 };
|
||||||
let p1 = ~Point { x: 5.0, y: 3.0 };
|
let p1 = box Point { x: 5.0, y: 3.0 };
|
||||||
|
|
||||||
println!("{:?}", compute_distance(origin, p1));
|
println!("{:?}", compute_distance(origin, p1));
|
||||||
}
|
}
|
||||||
|
@ -381,7 +382,7 @@ duration a 'lifetime'. Let's try a more complex example:
|
||||||
|
|
||||||
~~~rust
|
~~~rust
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut x = ~5;
|
let mut x = box 5;
|
||||||
if *x < 10 {
|
if *x < 10 {
|
||||||
let y = &x;
|
let y = &x;
|
||||||
println!("Oh no: {:?}", y);
|
println!("Oh no: {:?}", y);
|
||||||
|
@ -398,7 +399,7 @@ mutated, and therefore, lets us pass. This wouldn't work:
|
||||||
|
|
||||||
~~~rust{.ignore}
|
~~~rust{.ignore}
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut x = ~5;
|
let mut x = box 5;
|
||||||
if *x < 10 {
|
if *x < 10 {
|
||||||
let y = &x;
|
let y = &x;
|
||||||
*x -= 1;
|
*x -= 1;
|
||||||
|
@ -437,12 +438,12 @@ is best.
|
||||||
What does that mean? Don't do this:
|
What does that mean? Don't do this:
|
||||||
|
|
||||||
~~~rust
|
~~~rust
|
||||||
fn foo(x: ~int) -> ~int {
|
fn foo(x: Box<int>) -> Box<int> {
|
||||||
return ~*x;
|
return box *x;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = ~5;
|
let x = box 5;
|
||||||
let y = foo(x);
|
let y = foo(x);
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
@ -450,13 +451,13 @@ fn main() {
|
||||||
Do this:
|
Do this:
|
||||||
|
|
||||||
~~~rust
|
~~~rust
|
||||||
fn foo(x: ~int) -> int {
|
fn foo(x: Box<int>) -> int {
|
||||||
return *x;
|
return *x;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = ~5;
|
let x = box 5;
|
||||||
let y = ~foo(x);
|
let y = box foo(x);
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
@ -464,12 +465,12 @@ This gives you flexibility, without sacrificing performance. For example, this w
|
||||||
also work:
|
also work:
|
||||||
|
|
||||||
~~~rust
|
~~~rust
|
||||||
fn foo(x: ~int) -> int {
|
fn foo(x: Box<int>) -> int {
|
||||||
return *x;
|
return *x;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = ~5;
|
let x = box 5;
|
||||||
let y = @foo(x);
|
let y = @foo(x);
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
|
|
@ -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() {
|
fn main() {
|
||||||
{
|
{
|
||||||
let mut x = ~5;
|
let mut x = box 5;
|
||||||
*x = 10;
|
*x = 10;
|
||||||
} // `x` is freed here
|
} // `x` is freed here
|
||||||
|
|
||||||
|
|
|
@ -127,12 +127,13 @@ That's a great example for stack memory,
|
||||||
but what about heap memory?
|
but what about heap memory?
|
||||||
Rust has a second kind of pointer,
|
Rust has a second kind of pointer,
|
||||||
an 'owned box',
|
an 'owned box',
|
||||||
that you can create with a `~`.
|
that you can create with the `box` operator.
|
||||||
Check it out:
|
Check it out:
|
||||||
|
|
||||||
```
|
```
|
||||||
fn dangling() -> ~int {
|
|
||||||
let i = ~1234;
|
fn dangling() -> Box<int> {
|
||||||
|
let i = box 1234;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +144,7 @@ fn add_one() -> int {
|
||||||
```
|
```
|
||||||
|
|
||||||
Now instead of a stack allocated `1234`,
|
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,
|
Whereas `&` borrows a pointer to existing memory,
|
||||||
creating an owned box allocates memory on the heap and places a value in it,
|
creating an owned box allocates memory on the heap and places a value in it,
|
||||||
giving you the sole pointer to that memory.
|
giving you the sole pointer to that memory.
|
||||||
|
@ -151,7 +152,7 @@ You can roughly compare these two lines:
|
||||||
|
|
||||||
```
|
```
|
||||||
// Rust
|
// Rust
|
||||||
let i = ~1234;
|
let i = box 1234;
|
||||||
```
|
```
|
||||||
|
|
||||||
```notrust
|
```notrust
|
||||||
|
|
|
@ -1393,7 +1393,7 @@ to pointers to the trait name, used as a type.
|
||||||
# trait Shape { }
|
# trait Shape { }
|
||||||
# impl Shape for int { }
|
# impl Shape for int { }
|
||||||
# let mycircle = 0;
|
# 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,
|
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:
|
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 {
|
match x {
|
||||||
Cons(_, ~Nil) => fail!("singleton list"),
|
Cons(_, box Nil) => fail!("singleton list"),
|
||||||
Cons(..) => return,
|
Cons(..) => return,
|
||||||
Nil => fail!("empty list")
|
Nil => fail!("empty list")
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
The first pattern matches lists constructed by applying `Cons` to any head
|
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
|
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
|
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
|
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_pair(a: int, b: int) { }
|
||||||
# fn process_ten() { }
|
# 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 {
|
match x {
|
||||||
Cons(a, ~Cons(b, _)) => {
|
Cons(a, box Cons(b, _)) => {
|
||||||
process_pair(a,b);
|
process_pair(a,b);
|
||||||
}
|
}
|
||||||
Cons(10, _) => {
|
Cons(10, _) => {
|
||||||
|
@ -3135,17 +3135,17 @@ Subpatterns can also be bound to variables by the use of the syntax
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
enum List { Nil, Cons(uint, ~List) }
|
enum List { Nil, Cons(uint, Box<List>) }
|
||||||
|
|
||||||
fn is_sorted(list: &List) -> bool {
|
fn is_sorted(list: &List) -> bool {
|
||||||
match *list {
|
match *list {
|
||||||
Nil | Cons(_, ~Nil) => true,
|
Nil | Cons(_, box Nil) => true,
|
||||||
Cons(x, ref r @ ~Cons(y, _)) => (x <= y) && is_sorted(*r)
|
Cons(x, ref r @ box Cons(y, _)) => (x <= y) && is_sorted(*r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
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));
|
assert!(is_sorted(&a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3411,10 +3411,10 @@ An example of a *recursive* type and its use:
|
||||||
~~~~
|
~~~~
|
||||||
enum List<T> {
|
enum List<T> {
|
||||||
Nil,
|
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
|
### Pointer types
|
||||||
|
@ -3563,12 +3563,12 @@ impl Printable for int {
|
||||||
fn to_string(&self) -> ~str { self.to_str() }
|
fn to_string(&self) -> ~str { self.to_str() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print(a: ~Printable) {
|
fn print(a: Box<Printable>) {
|
||||||
println!("{}", a.to_string());
|
println!("{}", a.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
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 {
|
trait Changer {
|
||||||
fn change(mut self) -> Self;
|
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
|
### Owned boxes
|
||||||
|
|
||||||
An _owned box_ is a reference to a heap allocation holding another value, which is constructed
|
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:
|
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
|
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.
|
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;
|
let y = x;
|
||||||
// attempting to use `x` will result in an error here
|
// attempting to use `x` will result in an error here
|
||||||
~~~~
|
~~~~
|
||||||
|
|
|
@ -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
|
dynamic failures are possible from accessing freed resources. When a task
|
||||||
fails, destructors of all objects in the task are called.
|
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
|
// 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
|
// 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
|
// 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
|
// `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
|
// when `a` goes out of scope, the destructor for the `~int` in the struct's
|
||||||
// field is called
|
// field is called
|
||||||
|
|
||||||
// `b` is mutable, and the mutability is inherited by the objects it owns
|
// `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;
|
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
|
directly inside `Cons`, making it at least as big as the sum of both types. The
|
||||||
type was invalid because the size was infinite!
|
type was invalid because the size was infinite!
|
||||||
|
|
||||||
An *owned box* (`~`) uses a dynamic memory allocation to provide the invariant
|
An *owned box* (`Box`, located in the `std::owned` module) uses a dynamic memory
|
||||||
of always being the size of a pointer, regardless of the contained type. This
|
allocation to provide the invariant of always being the size of a pointer,
|
||||||
can be leveraged to create a valid `List` definition:
|
regardless of the contained type. This can be leveraged to create a valid `List`
|
||||||
|
definition:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
enum List {
|
enum List {
|
||||||
Cons(u32, ~List),
|
Cons(u32, Box<List>),
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
@ -1040,10 +1042,10 @@ Consider an instance of our `List` type:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
# enum List {
|
# enum List {
|
||||||
# Cons(u32, ~List),
|
# Cons(u32, Box<List>),
|
||||||
# Nil
|
# 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
|
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}
|
~~~ {.notrust}
|
||||||
List box List box List box List box
|
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 {
|
# enum List {
|
||||||
# Cons(u32, ~List),
|
# Cons(u32, Box<List>),
|
||||||
# Nil
|
# 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
|
let ys = xs; // copies `Cons(u32, pointer)` shallowly
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
@ -1087,7 +1089,7 @@ location cannot be used unless it is reinitialized.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
# enum List {
|
# enum List {
|
||||||
# Cons(u32, ~List),
|
# Cons(u32, Box<List>),
|
||||||
# Nil
|
# Nil
|
||||||
# }
|
# }
|
||||||
let mut xs = 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:
|
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 y = x.clone(); // `y` is a newly allocated box
|
||||||
let z = x; // no new memory allocated, `x` can no longer be used
|
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}
|
~~~{.ignore}
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
enum List {
|
enum List {
|
||||||
Cons(u32, ~List),
|
Cons(u32, Box<List>),
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = Cons(5, ~Nil);
|
let x = Cons(5, box Nil);
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
|
|
||||||
// `x` can still be used!
|
// `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:
|
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
|
let mut s = r; // box becomes mutable
|
||||||
*s += 1;
|
*s += 1;
|
||||||
let t = s; // box becomes immutable
|
let t = s; // box becomes immutable
|
||||||
|
@ -1146,12 +1148,12 @@ advantage of moves:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
enum List {
|
enum List {
|
||||||
Cons(u32, ~List),
|
Cons(u32, Box<List>),
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepend(xs: List, value: u32) -> List {
|
fn prepend(xs: List, value: u32) -> List {
|
||||||
Cons(value, ~xs)
|
Cons(value, box xs)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut xs = Nil;
|
let mut xs = Nil;
|
||||||
|
@ -1186,7 +1188,7 @@ by-value. A recursive definition of equality using references is as follows:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
# enum List {
|
# enum List {
|
||||||
# Cons(u32, ~List),
|
# Cons(u32, Box<List>),
|
||||||
# Nil
|
# Nil
|
||||||
# }
|
# }
|
||||||
fn eq(xs: &List, ys: &List) -> bool {
|
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.
|
// If we have reached the end of both lists, they are equal.
|
||||||
(&Nil, &Nil) => true,
|
(&Nil, &Nil) => true,
|
||||||
// If the current elements of both lists are equal, keep going.
|
// 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 x == y => eq(next_xs, next_ys),
|
||||||
// If the current elements are not equal, the lists are not equal.
|
// If the current elements are not equal, the lists are not equal.
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let xs = Cons(5, ~Cons(10, ~Nil));
|
let xs = Cons(5, box Cons(10, box Nil));
|
||||||
let ys = Cons(5, ~Cons(10, ~Nil));
|
let ys = Cons(5, box Cons(10, box Nil));
|
||||||
assert!(eq(&xs, &ys));
|
assert!(eq(&xs, &ys));
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
@ -1223,7 +1225,7 @@ The `u32` in the previous definition can be substituted with a type parameter:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
enum List<T> {
|
enum List<T> {
|
||||||
Cons(T, ~List<T>),
|
Cons(T, Box<List<T>>),
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
@ -1233,11 +1235,11 @@ definition has to be updated too:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
# enum List<T> {
|
# enum List<T> {
|
||||||
# Cons(T, ~List<T>),
|
# Cons(T, Box<List<T>>),
|
||||||
# Nil
|
# Nil
|
||||||
# }
|
# }
|
||||||
fn prepend<T>(xs: List<T>, value: T) -> List<T> {
|
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> {
|
# enum List<T> {
|
||||||
# Cons(T, ~List<T>),
|
# Cons(T, Box<List<T>>),
|
||||||
# Nil
|
# Nil
|
||||||
# }
|
# }
|
||||||
# fn prepend<T>(xs: List<T>, value: T) -> List<T> {
|
# 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.
|
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>`.
|
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> {
|
# enum List<T> {
|
||||||
# Cons(T, ~List<T>),
|
# Cons(T, Box<List<T>>),
|
||||||
# Nil
|
# Nil
|
||||||
# }
|
# }
|
||||||
# fn prepend<T>(xs: List<T>, value: T) -> List<T> {
|
# fn prepend<T>(xs: List<T>, value: T) -> List<T> {
|
||||||
# Cons(value, ~xs)
|
# Cons(value, box xs)
|
||||||
# }
|
# }
|
||||||
let mut xs: List<int> = Nil::<int>;
|
let mut xs: List<int> = Nil::<int>;
|
||||||
xs = prepend::<int>(xs, 10);
|
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> {
|
# enum List<T> {
|
||||||
# Cons(T, ~List<T>),
|
# Cons(T, Box<List<T>>),
|
||||||
# Nil
|
# Nil
|
||||||
# }
|
# }
|
||||||
fn eq<T: Eq>(xs: &List<T>, ys: &List<T>) -> bool {
|
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.
|
// If we have reached the end of both lists, they are equal.
|
||||||
(&Nil, &Nil) => true,
|
(&Nil, &Nil) => true,
|
||||||
// If the current elements of both lists are equal, keep going.
|
// 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 x == y => eq(next_xs, next_ys),
|
||||||
// If the current elements are not equal, the lists are not equal.
|
// If the current elements are not equal, the lists are not equal.
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let xs = Cons('c', ~Cons('a', ~Cons('t', ~Nil)));
|
let xs = Cons('c', box Cons('a', box Cons('t', box Nil)));
|
||||||
let ys = Cons('c', ~Cons('a', ~Cons('t', ~Nil)));
|
let ys = Cons('c', box Cons('a', box Cons('t', box Nil)));
|
||||||
assert!(eq(&xs, &ys));
|
assert!(eq(&xs, &ys));
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
@ -1321,7 +1323,7 @@ on.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
# enum List<T> {
|
# enum List<T> {
|
||||||
# Cons(T, ~List<T>),
|
# Cons(T, Box<List<T>>),
|
||||||
# Nil
|
# Nil
|
||||||
# }
|
# }
|
||||||
impl<T: Eq> Eq for List<T> {
|
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.
|
// If we have reached the end of both lists, they are equal.
|
||||||
(&Nil, &Nil) => true,
|
(&Nil, &Nil) => true,
|
||||||
// If the current elements of both lists are equal, keep going.
|
// 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 x == y => next_xs == next_ys,
|
||||||
// If the current elements are not equal, the lists are not equal.
|
// If the current elements are not equal, the lists are not equal.
|
||||||
_ => false
|
_ => false
|
||||||
|
@ -1339,8 +1341,8 @@ impl<T: Eq> Eq for List<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let xs = Cons(5, ~Cons(10, ~Nil));
|
let xs = Cons(5, box Cons(10, box Nil));
|
||||||
let ys = Cons(5, ~Cons(10, ~Nil));
|
let ys = Cons(5, box Cons(10, box Nil));
|
||||||
// The methods below are part of the Eq trait,
|
// The methods below are part of the Eq trait,
|
||||||
// which we implemented on our linked list.
|
// which we implemented on our linked list.
|
||||||
assert!(xs.eq(&ys));
|
assert!(xs.eq(&ys));
|
||||||
|
@ -1373,7 +1375,7 @@ fn foo() -> (u64, u64, u64, u64, u64, u64) {
|
||||||
(5, 5, 5, 5, 5, 5)
|
(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
|
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
|
let mut y = 5; // mutable
|
||||||
y += 2;
|
y += 2;
|
||||||
|
|
||||||
let x = ~5; // immutable
|
let x = box 5; // immutable
|
||||||
let mut y = ~5; // mutable
|
let mut y = box 5; // mutable
|
||||||
*y += 2; // the `*` operator is needed to access the contained value
|
*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 }
|
# struct Point { x: f64, y: f64 }
|
||||||
let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
|
let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
|
||||||
let owned_box : ~Point = ~Point { x: 7.0, y: 9.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
|
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 };
|
# struct Point{ x: f64, y: f64 };
|
||||||
# let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
|
# let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
|
||||||
# let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 };
|
# let owned_box : Box<Point> = box Point { x: 7.0, y: 9.0 };
|
||||||
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
|
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
|
||||||
compute_distance(&on_the_stack, owned_box);
|
compute_distance(&on_the_stack, owned_box);
|
||||||
~~~
|
~~~
|
||||||
|
@ -1453,7 +1455,7 @@ route to the same data.
|
||||||
|
|
||||||
In the case of `owned_box`, however, no
|
In the case of `owned_box`, however, no
|
||||||
explicit action is necessary. The compiler will automatically convert
|
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
|
`&point`. This is another form of borrowing; in this case, the
|
||||||
contents of the owned box are being lent out.
|
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.
|
box or pointer, similarly to C.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
let owned = ~10;
|
let owned = box 10;
|
||||||
let borrowed = &20;
|
let borrowed = &20;
|
||||||
|
|
||||||
let sum = *owned + *borrowed;
|
let sum = *owned + *borrowed;
|
||||||
|
@ -1503,7 +1505,7 @@ assignments. Such an assignment modifies the value that the pointer
|
||||||
points to.
|
points to.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
let mut owned = ~10;
|
let mut owned = box 10;
|
||||||
|
|
||||||
let mut value = 20;
|
let mut value = 20;
|
||||||
let borrowed = &mut value;
|
let borrowed = &mut value;
|
||||||
|
@ -1520,8 +1522,8 @@ can sometimes make code awkward and parenthesis-filled.
|
||||||
# struct Point { x: f64, y: f64 }
|
# struct Point { x: f64, y: f64 }
|
||||||
# enum Shape { Rectangle(Point, Point) }
|
# enum Shape { Rectangle(Point, Point) }
|
||||||
# impl Shape { fn area(&self) -> int { 0 } }
|
# impl Shape { fn area(&self) -> int { 0 } }
|
||||||
let start = ~Point { x: 10.0, y: 20.0 };
|
let start = box Point { x: 10.0, y: 20.0 };
|
||||||
let end = ~Point { x: (*start).x + 100.0, y: (*start).y + 100.0 };
|
let end = box Point { x: (*start).x + 100.0, y: (*start).y + 100.0 };
|
||||||
let rect = &Rectangle(*start, *end);
|
let rect = &Rectangle(*start, *end);
|
||||||
let area = (*rect).area();
|
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 }
|
# struct Point { x: f64, y: f64 }
|
||||||
# enum Shape { Rectangle(Point, Point) }
|
# enum Shape { Rectangle(Point, Point) }
|
||||||
# impl Shape { fn area(&self) -> int { 0 } }
|
# impl Shape { fn area(&self) -> int { 0 } }
|
||||||
let start = ~Point { x: 10.0, y: 20.0 };
|
let start = box Point { x: 10.0, y: 20.0 };
|
||||||
let end = ~Point { x: start.x + 100.0, y: start.y + 100.0 };
|
let end = box Point { x: start.x + 100.0, y: start.y + 100.0 };
|
||||||
let rect = &Rectangle(*start, *end);
|
let rect = &Rectangle(*start, *end);
|
||||||
let area = rect.area();
|
let area = rect.area();
|
||||||
~~~
|
~~~
|
||||||
|
@ -1546,7 +1548,7 @@ something silly like
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
# struct Point { x: f64, y: f64 }
|
# 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);
|
println!("{:f}", point.x);
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
@ -1944,7 +1946,7 @@ impl Shape {
|
||||||
let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
|
let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
|
||||||
|
|
||||||
(&s).draw_reference();
|
(&s).draw_reference();
|
||||||
(~s).draw_owned();
|
(box s).draw_owned();
|
||||||
s.draw_value();
|
s.draw_value();
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
@ -1969,7 +1971,7 @@ to a reference.
|
||||||
// As with typical function arguments, owned pointers
|
// As with typical function arguments, owned pointers
|
||||||
// are automatically converted to references
|
// are automatically converted to references
|
||||||
|
|
||||||
(~s).draw_reference();
|
(box s).draw_reference();
|
||||||
|
|
||||||
// Unlike typical function arguments, the self value will
|
// Unlike typical function arguments, the self value will
|
||||||
// automatically be referenced ...
|
// automatically be referenced ...
|
||||||
|
@ -1979,7 +1981,7 @@ s.draw_reference();
|
||||||
(& &s).draw_reference();
|
(& &s).draw_reference();
|
||||||
|
|
||||||
// ... and dereferenced and borrowed
|
// ... and dereferenced and borrowed
|
||||||
(&~s).draw_reference();
|
(&box s).draw_reference();
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Implementations may also define standalone (sometimes called "static")
|
Implementations may also define standalone (sometimes called "static")
|
||||||
|
@ -2433,7 +2435,7 @@ an _object_.
|
||||||
|
|
||||||
~~~~
|
~~~~
|
||||||
# trait Drawable { fn draw(&self); }
|
# trait Drawable { fn draw(&self); }
|
||||||
fn draw_all(shapes: &[~Drawable]) {
|
fn draw_all(shapes: &[Box<Drawable>]) {
|
||||||
for shape in shapes.iter() { shape.draw(); }
|
for shape in shapes.iter() { shape.draw(); }
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
|
@ -2448,14 +2450,14 @@ to an object:
|
||||||
# trait Drawable { fn draw(&self); }
|
# trait Drawable { fn draw(&self); }
|
||||||
# fn new_circle() -> Circle { 1 }
|
# fn new_circle() -> Circle { 1 }
|
||||||
# fn new_rectangle() -> Rectangle { true }
|
# 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 Circle { fn draw(&self) { /* ... */ } }
|
||||||
impl Drawable for Rectangle { fn draw(&self) { /* ... */ } }
|
impl Drawable for Rectangle { fn draw(&self) { /* ... */ } }
|
||||||
|
|
||||||
let c: ~Circle = ~new_circle();
|
let c: Box<Circle> = box new_circle();
|
||||||
let r: ~Rectangle = ~new_rectangle();
|
let r: Box<Rectangle> = box new_rectangle();
|
||||||
draw_all([c as ~Drawable, r as ~Drawable]);
|
draw_all([c as Box<Drawable>, r as Box<Drawable>]);
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
We omit the code for `new_circle` and `new_rectangle`; imagine that
|
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.
|
only be referred to via one of the pointer types.
|
||||||
Other pointer types work as well.
|
Other pointer types work as well.
|
||||||
Casts to traits may only be done with compatible pointers so,
|
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;
|
# 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_circle() -> int { 1 }
|
||||||
# fn new_rectangle() -> int { 2 }
|
# fn new_rectangle() -> int { 2 }
|
||||||
// An owned object
|
// An owned object
|
||||||
let owny: ~Drawable = ~new_circle() as ~Drawable;
|
let owny: Box<Drawable> = box new_circle() as Box<Drawable>;
|
||||||
// A borrowed object
|
// A borrowed object
|
||||||
let stacky: &Drawable = &new_circle() as &Drawable;
|
let stacky: &Drawable = &new_circle() as &Drawable;
|
||||||
~~~
|
~~~
|
||||||
|
@ -2497,7 +2499,7 @@ valid types:
|
||||||
trait Foo {}
|
trait Foo {}
|
||||||
trait Bar<T> {}
|
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) { /* ... */ }
|
fn shareable_bar<T: Share>(b: &Bar<T>: Share) { /* ... */ }
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
|
@ -29,14 +29,14 @@ extern crate collections;
|
||||||
use std::cast::{transmute, transmute_mut_lifetime};
|
use std::cast::{transmute, transmute_mut_lifetime};
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::mem;
|
|
||||||
use std::ptr::read;
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::num;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::rt::global_heap;
|
|
||||||
use std::intrinsics::{TyDesc, get_tydesc};
|
use std::intrinsics::{TyDesc, get_tydesc};
|
||||||
use std::intrinsics;
|
use std::intrinsics;
|
||||||
|
use std::mem;
|
||||||
|
use std::num;
|
||||||
|
use std::ptr::read;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::rt::global_heap;
|
||||||
|
|
||||||
// The way arena uses arrays is really deeply awful. The arrays are
|
// The way arena uses arrays is really deeply awful. The arrays are
|
||||||
// allocated, and have capacities reserved, but the fill for the array
|
// allocated, and have capacities reserved, but the fill for the array
|
||||||
|
@ -339,12 +339,12 @@ pub struct TypedArena<T> {
|
||||||
end: *T,
|
end: *T,
|
||||||
|
|
||||||
/// A pointer to the first arena segment.
|
/// A pointer to the first arena segment.
|
||||||
first: Option<~TypedArenaChunk<T>>,
|
first: Option<Box<TypedArenaChunk<T>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TypedArenaChunk<T> {
|
struct TypedArenaChunk<T> {
|
||||||
/// Pointer to the next arena segment.
|
/// Pointer to the next arena segment.
|
||||||
next: Option<~TypedArenaChunk<T>>,
|
next: Option<Box<TypedArenaChunk<T>>>,
|
||||||
|
|
||||||
/// The number of elements that this chunk can hold.
|
/// The number of elements that this chunk can hold.
|
||||||
capacity: uint,
|
capacity: uint,
|
||||||
|
@ -354,7 +354,8 @@ struct TypedArenaChunk<T> {
|
||||||
|
|
||||||
impl<T> TypedArenaChunk<T> {
|
impl<T> TypedArenaChunk<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(next: Option<~TypedArenaChunk<T>>, capacity: uint) -> ~TypedArenaChunk<T> {
|
fn new(next: Option<Box<TypedArenaChunk<T>>>, capacity: uint)
|
||||||
|
-> Box<TypedArenaChunk<T>> {
|
||||||
let mut size = mem::size_of::<TypedArenaChunk<T>>();
|
let mut size = mem::size_of::<TypedArenaChunk<T>>();
|
||||||
size = round_up(size, mem::min_align_of::<T>());
|
size = round_up(size, mem::min_align_of::<T>());
|
||||||
let elem_size = mem::size_of::<T>();
|
let elem_size = mem::size_of::<T>();
|
||||||
|
@ -363,7 +364,7 @@ impl<T> TypedArenaChunk<T> {
|
||||||
|
|
||||||
let mut chunk = unsafe {
|
let mut chunk = unsafe {
|
||||||
let chunk = global_heap::exchange_malloc(size);
|
let chunk = global_heap::exchange_malloc(size);
|
||||||
let mut chunk: ~TypedArenaChunk<T> = cast::transmute(chunk);
|
let mut chunk: Box<TypedArenaChunk<T>> = cast::transmute(chunk);
|
||||||
mem::move_val_init(&mut chunk.next, next);
|
mem::move_val_init(&mut chunk.next, next);
|
||||||
chunk
|
chunk
|
||||||
};
|
};
|
||||||
|
|
|
@ -140,7 +140,8 @@ impl<K: TotalOrd, V> Node<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
///Creates a new branch node given a vector of an elements and a pointer to a rightmost child.
|
///Creates a new branch node given a vector of an elements and a pointer to a rightmost child.
|
||||||
fn new_branch(vec: Vec<BranchElt<K, V>>, right: ~Node<K, V>) -> Node<K, V> {
|
fn new_branch(vec: Vec<BranchElt<K, V>>, right: Box<Node<K, V>>)
|
||||||
|
-> Node<K, V> {
|
||||||
BranchNode(Branch::new(vec, right))
|
BranchNode(Branch::new(vec, right))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +271,7 @@ struct Leaf<K, V> {
|
||||||
//Vector of values with children, plus a rightmost child (greater than all)
|
//Vector of values with children, plus a rightmost child (greater than all)
|
||||||
struct Branch<K, V> {
|
struct Branch<K, V> {
|
||||||
elts: Vec<BranchElt<K,V>>,
|
elts: Vec<BranchElt<K,V>>,
|
||||||
rightmost_child: ~Node<K, V>
|
rightmost_child: Box<Node<K, V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -434,7 +435,8 @@ impl<K: fmt::Show + TotalOrd, V: fmt::Show> fmt::Show for Leaf<K, V> {
|
||||||
|
|
||||||
impl<K: TotalOrd, V> Branch<K, V> {
|
impl<K: TotalOrd, V> Branch<K, V> {
|
||||||
///Creates a new Branch from a vector of BranchElts and a rightmost child (a node).
|
///Creates a new Branch from a vector of BranchElts and a rightmost child (a node).
|
||||||
fn new(vec: Vec<BranchElt<K, V>>, right: ~Node<K, V>) -> Branch<K, V> {
|
fn new(vec: Vec<BranchElt<K, V>>, right: Box<Node<K, V>>)
|
||||||
|
-> Branch<K, V> {
|
||||||
Branch {
|
Branch {
|
||||||
elts: vec,
|
elts: vec,
|
||||||
rightmost_child: right
|
rightmost_child: right
|
||||||
|
@ -667,7 +669,7 @@ struct LeafElt<K, V> {
|
||||||
|
|
||||||
//A BranchElt has a left child in insertion to a key-value pair.
|
//A BranchElt has a left child in insertion to a key-value pair.
|
||||||
struct BranchElt<K, V> {
|
struct BranchElt<K, V> {
|
||||||
left: ~Node<K, V>,
|
left: Box<Node<K, V>>,
|
||||||
key: K,
|
key: K,
|
||||||
value: V
|
value: V
|
||||||
}
|
}
|
||||||
|
@ -719,7 +721,7 @@ impl<K: fmt::Show + TotalOrd, V: fmt::Show> fmt::Show for LeafElt<K, V> {
|
||||||
|
|
||||||
impl<K: TotalOrd, V> BranchElt<K, V> {
|
impl<K: TotalOrd, V> BranchElt<K, V> {
|
||||||
///Creates a new BranchElt from a supplied key, value, and left child.
|
///Creates a new BranchElt from a supplied key, value, and left child.
|
||||||
fn new(k: K, v: V, n: ~Node<K, V>) -> BranchElt<K, V> {
|
fn new(k: K, v: V, n: Box<Node<K, V>>) -> BranchElt<K, V> {
|
||||||
BranchElt {
|
BranchElt {
|
||||||
left: n,
|
left: n,
|
||||||
key: k,
|
key: k,
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
//! DList implements the trait Deque. It should be imported with `use
|
//! DList implements the trait Deque. It should be imported with `use
|
||||||
//! collections::deque::Deque`.
|
//! collections::deque::Deque`.
|
||||||
|
|
||||||
|
|
||||||
// DList is constructed like a singly-linked list over the field `next`.
|
// DList is constructed like a singly-linked list over the field `next`.
|
||||||
// including the last link being None; each Node owns its `next` field.
|
// including the last link being None; each Node owns its `next` field.
|
||||||
//
|
//
|
||||||
|
@ -23,10 +22,10 @@
|
||||||
// the reverse direction.
|
// the reverse direction.
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::mem::{replace, swap};
|
|
||||||
use std::ptr;
|
|
||||||
use std::iter::Rev;
|
use std::iter::Rev;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
use std::mem::{replace, swap};
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
use deque::Deque;
|
use deque::Deque;
|
||||||
|
|
||||||
|
@ -37,7 +36,7 @@ pub struct DList<T> {
|
||||||
list_tail: Rawlink<Node<T>>,
|
list_tail: Rawlink<Node<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Link<T> = Option<~Node<T>>;
|
type Link<T> = Option<Box<Node<T>>>;
|
||||||
struct Rawlink<T> { p: *mut T }
|
struct Rawlink<T> { p: *mut T }
|
||||||
|
|
||||||
struct Node<T> {
|
struct Node<T> {
|
||||||
|
@ -118,7 +117,8 @@ impl<T> Node<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the .prev field on `next`, then return `Some(next)`
|
/// Set the .prev field on `next`, then return `Some(next)`
|
||||||
fn link_with_prev<T>(mut next: ~Node<T>, prev: Rawlink<Node<T>>) -> Link<T> {
|
fn link_with_prev<T>(mut next: Box<Node<T>>, prev: Rawlink<Node<T>>)
|
||||||
|
-> Link<T> {
|
||||||
next.prev = prev;
|
next.prev = prev;
|
||||||
Some(next)
|
Some(next)
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ impl<T> Mutable for DList<T> {
|
||||||
impl<T> DList<T> {
|
impl<T> DList<T> {
|
||||||
/// Add a Node first in the list
|
/// Add a Node first in the list
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push_front_node(&mut self, mut new_head: ~Node<T>) {
|
fn push_front_node(&mut self, mut new_head: Box<Node<T>>) {
|
||||||
match self.list_head {
|
match self.list_head {
|
||||||
None => {
|
None => {
|
||||||
self.list_tail = Rawlink::some(new_head);
|
self.list_tail = Rawlink::some(new_head);
|
||||||
|
@ -168,7 +168,7 @@ impl<T> DList<T> {
|
||||||
|
|
||||||
/// Remove the first Node and return it, or None if the list is empty
|
/// Remove the first Node and return it, or None if the list is empty
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pop_front_node(&mut self) -> Option<~Node<T>> {
|
fn pop_front_node(&mut self) -> Option<Box<Node<T>>> {
|
||||||
self.list_head.take().map(|mut front_node| {
|
self.list_head.take().map(|mut front_node| {
|
||||||
self.length -= 1;
|
self.length -= 1;
|
||||||
match front_node.next.take() {
|
match front_node.next.take() {
|
||||||
|
@ -181,7 +181,7 @@ impl<T> DList<T> {
|
||||||
|
|
||||||
/// Add a Node last in the list
|
/// Add a Node last in the list
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push_back_node(&mut self, mut new_tail: ~Node<T>) {
|
fn push_back_node(&mut self, mut new_tail: Box<Node<T>>) {
|
||||||
match self.list_tail.resolve() {
|
match self.list_tail.resolve() {
|
||||||
None => return self.push_front_node(new_tail),
|
None => return self.push_front_node(new_tail),
|
||||||
Some(tail) => {
|
Some(tail) => {
|
||||||
|
@ -194,7 +194,7 @@ impl<T> DList<T> {
|
||||||
|
|
||||||
/// Remove the last Node and return it, or None if the list is empty
|
/// Remove the last Node and return it, or None if the list is empty
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pop_back_node(&mut self) -> Option<~Node<T>> {
|
fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
|
||||||
self.list_tail.resolve().map_or(None, |tail| {
|
self.list_tail.resolve().map_or(None, |tail| {
|
||||||
self.length -= 1;
|
self.length -= 1;
|
||||||
self.list_tail = tail.prev;
|
self.list_tail = tail.prev;
|
||||||
|
@ -245,7 +245,7 @@ impl<T> Deque<T> for DList<T> {
|
||||||
///
|
///
|
||||||
/// O(1)
|
/// O(1)
|
||||||
fn pop_front(&mut self) -> Option<T> {
|
fn pop_front(&mut self) -> Option<T> {
|
||||||
self.pop_front_node().map(|~Node{value, ..}| value)
|
self.pop_front_node().map(|box Node{value, ..}| value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an element last in the list
|
/// Add an element last in the list
|
||||||
|
@ -259,7 +259,7 @@ impl<T> Deque<T> for DList<T> {
|
||||||
///
|
///
|
||||||
/// O(1)
|
/// O(1)
|
||||||
fn pop_back(&mut self) -> Option<T> {
|
fn pop_back(&mut self) -> Option<T> {
|
||||||
self.pop_back_node().map(|~Node{value, ..}| value)
|
self.pop_back_node().map(|box Node{value, ..}| value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,7 +432,7 @@ impl<T> Drop for DList<T> {
|
||||||
match tail.resolve() {
|
match tail.resolve() {
|
||||||
None => break,
|
None => break,
|
||||||
Some(prev) => {
|
Some(prev) => {
|
||||||
prev.next.take(); // release ~Node<T>
|
prev.next.take(); // release Box<Node<T>>
|
||||||
tail = prev.prev;
|
tail = prev.prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,7 +531,7 @@ pub trait ListInsertion<A> {
|
||||||
|
|
||||||
// private methods for MutItems
|
// private methods for MutItems
|
||||||
impl<'a, A> MutItems<'a, A> {
|
impl<'a, A> MutItems<'a, A> {
|
||||||
fn insert_next_node(&mut self, mut ins_node: ~Node<A>) {
|
fn insert_next_node(&mut self, mut ins_node: Box<Node<A>>) {
|
||||||
// Insert before `self.head` so that it is between the
|
// Insert before `self.head` so that it is between the
|
||||||
// previously yielded element and self.head.
|
// previously yielded element and self.head.
|
||||||
//
|
//
|
||||||
|
@ -671,24 +671,24 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
let mut m: DList<~int> = DList::new();
|
let mut m: DList<Box<int>> = DList::new();
|
||||||
assert_eq!(m.pop_front(), None);
|
assert_eq!(m.pop_front(), None);
|
||||||
assert_eq!(m.pop_back(), None);
|
assert_eq!(m.pop_back(), None);
|
||||||
assert_eq!(m.pop_front(), None);
|
assert_eq!(m.pop_front(), None);
|
||||||
m.push_front(box 1);
|
m.push_front(box 1);
|
||||||
assert_eq!(m.pop_front(), Some(~1));
|
assert_eq!(m.pop_front(), Some(box 1));
|
||||||
m.push_back(box 2);
|
m.push_back(box 2);
|
||||||
m.push_back(box 3);
|
m.push_back(box 3);
|
||||||
assert_eq!(m.len(), 2);
|
assert_eq!(m.len(), 2);
|
||||||
assert_eq!(m.pop_front(), Some(~2));
|
assert_eq!(m.pop_front(), Some(box 2));
|
||||||
assert_eq!(m.pop_front(), Some(~3));
|
assert_eq!(m.pop_front(), Some(box 3));
|
||||||
assert_eq!(m.len(), 0);
|
assert_eq!(m.len(), 0);
|
||||||
assert_eq!(m.pop_front(), None);
|
assert_eq!(m.pop_front(), None);
|
||||||
m.push_back(box 1);
|
m.push_back(box 1);
|
||||||
m.push_back(box 3);
|
m.push_back(box 3);
|
||||||
m.push_back(box 5);
|
m.push_back(box 5);
|
||||||
m.push_back(box 7);
|
m.push_back(box 7);
|
||||||
assert_eq!(m.pop_front(), Some(~1));
|
assert_eq!(m.pop_front(), Some(box 1));
|
||||||
|
|
||||||
let mut n = DList::new();
|
let mut n = DList::new();
|
||||||
n.push_front(2);
|
n.push_front(2);
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct LruEntry<K, V> {
|
||||||
|
|
||||||
/// An LRU Cache.
|
/// An LRU Cache.
|
||||||
pub struct LruCache<K, V> {
|
pub struct LruCache<K, V> {
|
||||||
map: HashMap<KeyRef<K>, ~LruEntry<K, V>>,
|
map: HashMap<KeyRef<K>, Box<LruEntry<K, V>>>,
|
||||||
max_size: uint,
|
max_size: uint,
|
||||||
head: *mut LruEntry<K, V>,
|
head: *mut LruEntry<K, V>,
|
||||||
}
|
}
|
||||||
|
@ -241,9 +241,9 @@ impl<K: Hash + TotalEq, V> Mutable for LruCache<K, V> {
|
||||||
impl<K, V> Drop for LruCache<K, V> {
|
impl<K, V> Drop for LruCache<K, V> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let node: ~LruEntry<K, V> = cast::transmute(self.head);
|
let node: Box<LruEntry<K, V>> = cast::transmute(self.head);
|
||||||
// Prevent compiler from trying to drop the un-initialized field in the sigil node.
|
// Prevent compiler from trying to drop the un-initialized field in the sigil node.
|
||||||
let ~LruEntry { key: k, value: v, .. } = node;
|
let box LruEntry { key: k, value: v, .. } = node;
|
||||||
cast::forget(k);
|
cast::forget(k);
|
||||||
cast::forget(v);
|
cast::forget(v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,24 +270,24 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push_unique() {
|
fn test_push_unique() {
|
||||||
let mut heap = PriorityQueue::from_vec(vec!(~2, ~4, ~9));
|
let mut heap = PriorityQueue::from_vec(vec!(box 2, box 4, box 9));
|
||||||
assert_eq!(heap.len(), 3);
|
assert_eq!(heap.len(), 3);
|
||||||
assert!(*heap.top() == ~9);
|
assert!(*heap.top() == box 9);
|
||||||
heap.push(box 11);
|
heap.push(box 11);
|
||||||
assert_eq!(heap.len(), 4);
|
assert_eq!(heap.len(), 4);
|
||||||
assert!(*heap.top() == ~11);
|
assert!(*heap.top() == box 11);
|
||||||
heap.push(box 5);
|
heap.push(box 5);
|
||||||
assert_eq!(heap.len(), 5);
|
assert_eq!(heap.len(), 5);
|
||||||
assert!(*heap.top() == ~11);
|
assert!(*heap.top() == box 11);
|
||||||
heap.push(box 27);
|
heap.push(box 27);
|
||||||
assert_eq!(heap.len(), 6);
|
assert_eq!(heap.len(), 6);
|
||||||
assert!(*heap.top() == ~27);
|
assert!(*heap.top() == box 27);
|
||||||
heap.push(box 3);
|
heap.push(box 3);
|
||||||
assert_eq!(heap.len(), 7);
|
assert_eq!(heap.len(), 7);
|
||||||
assert!(*heap.top() == ~27);
|
assert!(*heap.top() == box 27);
|
||||||
heap.push(box 103);
|
heap.push(box 103);
|
||||||
assert_eq!(heap.len(), 8);
|
assert_eq!(heap.len(), 8);
|
||||||
assert!(*heap.top() == ~103);
|
assert!(*heap.top() == box 103);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -465,7 +465,7 @@ mod test_map {
|
||||||
assert!(!called);
|
assert!(!called);
|
||||||
called = true;
|
called = true;
|
||||||
assert_eq!(k, 1);
|
assert_eq!(k, 1);
|
||||||
assert_eq!(v, ~2);
|
assert_eq!(v, box 2);
|
||||||
}
|
}
|
||||||
assert!(called);
|
assert!(called);
|
||||||
m.insert(2, box 1);
|
m.insert(2, box 1);
|
||||||
|
|
|
@ -36,7 +36,7 @@ use std::ptr;
|
||||||
#[allow(missing_doc)]
|
#[allow(missing_doc)]
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct TreeMap<K, V> {
|
pub struct TreeMap<K, V> {
|
||||||
root: Option<~TreeNode<K, V>>,
|
root: Option<Box<TreeNode<K, V>>>,
|
||||||
length: uint
|
length: uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ impl<K: TotalOrd, V> Mutable for TreeMap<K, V> {
|
||||||
|
|
||||||
impl<K: TotalOrd, V> Map<K, V> for TreeMap<K, V> {
|
impl<K: TotalOrd, V> Map<K, V> for TreeMap<K, V> {
|
||||||
fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
|
fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
|
||||||
let mut current: &'a Option<~TreeNode<K, V>> = &self.root;
|
let mut current: &'a Option<Box<TreeNode<K, V>>> = &self.root;
|
||||||
loop {
|
loop {
|
||||||
match *current {
|
match *current {
|
||||||
Some(ref r) => {
|
Some(ref r) => {
|
||||||
|
@ -157,7 +157,7 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
|
||||||
let TreeMap { root: root, length: length } = self;
|
let TreeMap { root: root, length: length } = self;
|
||||||
let stk = match root {
|
let stk = match root {
|
||||||
None => vec!(),
|
None => vec!(),
|
||||||
Some(~tn) => vec!(tn)
|
Some(box tn) => vec!(tn)
|
||||||
};
|
};
|
||||||
MoveEntries {
|
MoveEntries {
|
||||||
stack: stk,
|
stack: stk,
|
||||||
|
@ -317,7 +317,7 @@ macro_rules! define_iterator {
|
||||||
($name:ident,
|
($name:ident,
|
||||||
$rev_name:ident,
|
$rev_name:ident,
|
||||||
|
|
||||||
// the function to go from &m Option<~TreeNode> to *m TreeNode
|
// the function to go from &m Option<Box<TreeNode>> to *m TreeNode
|
||||||
deref = $deref:ident,
|
deref = $deref:ident,
|
||||||
|
|
||||||
// see comment on `addr!`, this is just an optional `mut`, but
|
// see comment on `addr!`, this is just an optional `mut`, but
|
||||||
|
@ -441,7 +441,7 @@ define_iterator! {
|
||||||
addr_mut = mut
|
addr_mut = mut
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deref<'a, K, V>(node: &'a Option<~TreeNode<K, V>>) -> *TreeNode<K, V> {
|
fn deref<'a, K, V>(node: &'a Option<Box<TreeNode<K, V>>>) -> *TreeNode<K, V> {
|
||||||
match *node {
|
match *node {
|
||||||
Some(ref n) => {
|
Some(ref n) => {
|
||||||
let n: &TreeNode<K, V> = *n;
|
let n: &TreeNode<K, V> = *n;
|
||||||
|
@ -451,7 +451,8 @@ fn deref<'a, K, V>(node: &'a Option<~TreeNode<K, V>>) -> *TreeNode<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mut_deref<K, V>(x: &mut Option<~TreeNode<K, V>>) -> *mut TreeNode<K, V> {
|
fn mut_deref<K, V>(x: &mut Option<Box<TreeNode<K, V>>>)
|
||||||
|
-> *mut TreeNode<K, V> {
|
||||||
match *x {
|
match *x {
|
||||||
Some(ref mut n) => {
|
Some(ref mut n) => {
|
||||||
let n: &mut TreeNode<K, V> = *n;
|
let n: &mut TreeNode<K, V> = *n;
|
||||||
|
@ -482,7 +483,7 @@ impl<K, V> Iterator<(K, V)> for MoveEntries<K,V> {
|
||||||
} = self.stack.pop().unwrap();
|
} = self.stack.pop().unwrap();
|
||||||
|
|
||||||
match left {
|
match left {
|
||||||
Some(~left) => {
|
Some(box left) => {
|
||||||
let n = TreeNode {
|
let n = TreeNode {
|
||||||
key: key,
|
key: key,
|
||||||
value: value,
|
value: value,
|
||||||
|
@ -495,7 +496,7 @@ impl<K, V> Iterator<(K, V)> for MoveEntries<K,V> {
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
match right {
|
match right {
|
||||||
Some(~right) => self.stack.push(right),
|
Some(box right) => self.stack.push(right),
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
self.remaining -= 1;
|
self.remaining -= 1;
|
||||||
|
@ -759,8 +760,8 @@ impl<'a, T: TotalOrd> Iterator<&'a T> for UnionItems<'a, T> {
|
||||||
struct TreeNode<K, V> {
|
struct TreeNode<K, V> {
|
||||||
key: K,
|
key: K,
|
||||||
value: V,
|
value: V,
|
||||||
left: Option<~TreeNode<K, V>>,
|
left: Option<Box<TreeNode<K, V>>>,
|
||||||
right: Option<~TreeNode<K, V>>,
|
right: Option<Box<TreeNode<K, V>>>,
|
||||||
level: uint
|
level: uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +774,7 @@ impl<K: TotalOrd, V> TreeNode<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove left horizontal link by rotating right
|
// Remove left horizontal link by rotating right
|
||||||
fn skew<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
|
fn skew<K: TotalOrd, V>(node: &mut Box<TreeNode<K, V>>) {
|
||||||
if node.left.as_ref().map_or(false, |x| x.level == node.level) {
|
if node.left.as_ref().map_or(false, |x| x.level == node.level) {
|
||||||
let mut save = node.left.take_unwrap();
|
let mut save = node.left.take_unwrap();
|
||||||
swap(&mut node.left, &mut save.right); // save.right now None
|
swap(&mut node.left, &mut save.right); // save.right now None
|
||||||
|
@ -784,7 +785,7 @@ fn skew<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
|
||||||
|
|
||||||
// Remove dual horizontal link by rotating left and increasing level of
|
// Remove dual horizontal link by rotating left and increasing level of
|
||||||
// the parent
|
// the parent
|
||||||
fn split<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
|
fn split<K: TotalOrd, V>(node: &mut Box<TreeNode<K, V>>) {
|
||||||
if node.right.as_ref().map_or(false,
|
if node.right.as_ref().map_or(false,
|
||||||
|x| x.right.as_ref().map_or(false, |y| y.level == node.level)) {
|
|x| x.right.as_ref().map_or(false, |y| y.level == node.level)) {
|
||||||
let mut save = node.right.take_unwrap();
|
let mut save = node.right.take_unwrap();
|
||||||
|
@ -795,7 +796,7 @@ fn split<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_mut<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
|
fn find_mut<'r, K: TotalOrd, V>(node: &'r mut Option<Box<TreeNode<K, V>>>,
|
||||||
key: &K)
|
key: &K)
|
||||||
-> Option<&'r mut V> {
|
-> Option<&'r mut V> {
|
||||||
match *node {
|
match *node {
|
||||||
|
@ -810,7 +811,7 @@ fn find_mut<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
|
fn insert<K: TotalOrd, V>(node: &mut Option<Box<TreeNode<K, V>>>,
|
||||||
key: K, value: V) -> Option<V> {
|
key: K, value: V) -> Option<V> {
|
||||||
match *node {
|
match *node {
|
||||||
Some(ref mut save) => {
|
Some(ref mut save) => {
|
||||||
|
@ -840,10 +841,10 @@ fn insert<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
|
fn remove<K: TotalOrd, V>(node: &mut Option<Box<TreeNode<K, V>>>,
|
||||||
key: &K) -> Option<V> {
|
key: &K) -> Option<V> {
|
||||||
fn heir_swap<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>,
|
fn heir_swap<K: TotalOrd, V>(node: &mut Box<TreeNode<K, V>>,
|
||||||
child: &mut Option<~TreeNode<K, V>>) {
|
child: &mut Option<Box<TreeNode<K, V>>>) {
|
||||||
// *could* be done without recursion, but it won't borrow check
|
// *could* be done without recursion, but it won't borrow check
|
||||||
for x in child.mut_iter() {
|
for x in child.mut_iter() {
|
||||||
if x.right.is_some() {
|
if x.right.is_some() {
|
||||||
|
@ -877,13 +878,13 @@ fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
|
||||||
(remove(&mut save.left, key), true)
|
(remove(&mut save.left, key), true)
|
||||||
} else {
|
} else {
|
||||||
let new = save.left.take_unwrap();
|
let new = save.left.take_unwrap();
|
||||||
let ~TreeNode{value, ..} = replace(save, new);
|
let box TreeNode{value, ..} = replace(save, new);
|
||||||
*save = save.left.take_unwrap();
|
*save = save.left.take_unwrap();
|
||||||
(Some(value), true)
|
(Some(value), true)
|
||||||
}
|
}
|
||||||
} else if save.right.is_some() {
|
} else if save.right.is_some() {
|
||||||
let new = save.right.take_unwrap();
|
let new = save.right.take_unwrap();
|
||||||
let ~TreeNode{value, ..} = replace(save, new);
|
let box TreeNode{value, ..} = replace(save, new);
|
||||||
(Some(value), true)
|
(Some(value), true)
|
||||||
} else {
|
} else {
|
||||||
(None, false)
|
(None, false)
|
||||||
|
@ -919,7 +920,7 @@ fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return match node.take() {
|
return match node.take() {
|
||||||
Some(~TreeNode{value, ..}) => Some(value), None => fail!()
|
Some(box TreeNode{value, ..}) => Some(value), None => fail!()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -959,7 +960,6 @@ impl<T: TotalOrd> Extendable<T> for TreeSet<T> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_treemap {
|
mod test_treemap {
|
||||||
|
|
||||||
use super::{TreeMap, TreeNode};
|
use super::{TreeMap, TreeNode};
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
@ -1053,8 +1053,8 @@ mod test_treemap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_left<K: TotalOrd, V>(node: &Option<~TreeNode<K, V>>,
|
fn check_left<K: TotalOrd, V>(node: &Option<Box<TreeNode<K, V>>>,
|
||||||
parent: &~TreeNode<K, V>) {
|
parent: &Box<TreeNode<K, V>>) {
|
||||||
match *node {
|
match *node {
|
||||||
Some(ref r) => {
|
Some(ref r) => {
|
||||||
assert_eq!(r.key.cmp(&parent.key), Less);
|
assert_eq!(r.key.cmp(&parent.key), Less);
|
||||||
|
@ -1066,8 +1066,8 @@ mod test_treemap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_right<K: TotalOrd, V>(node: &Option<~TreeNode<K, V>>,
|
fn check_right<K: TotalOrd, V>(node: &Option<Box<TreeNode<K, V>>>,
|
||||||
parent: &~TreeNode<K, V>,
|
parent: &Box<TreeNode<K, V>>,
|
||||||
parent_red: bool) {
|
parent_red: bool) {
|
||||||
match *node {
|
match *node {
|
||||||
Some(ref r) => {
|
Some(ref r) => {
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
|
|
||||||
//! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types)
|
//! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types)
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
use std::uint;
|
|
||||||
use std::mem::init;
|
use std::mem::init;
|
||||||
use std::slice;
|
use std::mem;
|
||||||
use std::slice::{Items, MutItems};
|
use std::slice::{Items, MutItems};
|
||||||
|
use std::slice;
|
||||||
|
use std::uint;
|
||||||
|
|
||||||
// FIXME: #5244: need to manually update the TrieNode constructor
|
// FIXME: #5244: need to manually update the TrieNode constructor
|
||||||
static SHIFT: uint = 4;
|
static SHIFT: uint = 4;
|
||||||
|
@ -23,7 +23,7 @@ static MASK: uint = SIZE - 1;
|
||||||
static NUM_CHUNKS: uint = uint::BITS / SHIFT;
|
static NUM_CHUNKS: uint = uint::BITS / SHIFT;
|
||||||
|
|
||||||
enum Child<T> {
|
enum Child<T> {
|
||||||
Internal(~TrieNode<T>),
|
Internal(Box<TrieNode<T>>),
|
||||||
External(uint, T),
|
External(uint, T),
|
||||||
Nothing
|
Nothing
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,14 +66,15 @@ use syntax::parse::token::InternedString;
|
||||||
#[macro_registrar]
|
#[macro_registrar]
|
||||||
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
|
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
|
||||||
register(token::intern("fourcc"),
|
register(token::intern("fourcc"),
|
||||||
NormalTT(~BasicMacroExpander {
|
NormalTT(box BasicMacroExpander {
|
||||||
expander: expand_syntax_ext,
|
expander: expand_syntax_ext,
|
||||||
span: None,
|
span: None,
|
||||||
},
|
},
|
||||||
None));
|
None));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
|
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||||
|
-> Box<base::MacResult> {
|
||||||
let (expr, endian) = parse_tts(cx, tts);
|
let (expr, endian) = parse_tts(cx, tts);
|
||||||
|
|
||||||
let little = match endian {
|
let little = match endian {
|
||||||
|
|
|
@ -18,7 +18,7 @@ use std::slice;
|
||||||
|
|
||||||
// Note 2: Once Dynamically Sized Types (DST) lands, it might be
|
// Note 2: Once Dynamically Sized Types (DST) lands, it might be
|
||||||
// reasonable to replace this with something like `enum MaybeOwned<'a,
|
// reasonable to replace this with something like `enum MaybeOwned<'a,
|
||||||
// Sized? U>{ Owned(~U), Borrowed(&'a U) }`; and then `U` could be
|
// Sized? U>{ Owned(Box<U>), Borrowed(&'a U) }`; and then `U` could be
|
||||||
// instantiated with `[T]` or `str`, etc. Of course, that would imply
|
// instantiated with `[T]` or `str`, etc. Of course, that would imply
|
||||||
// removing the `Growable` variant, which relates to note 1 above.
|
// removing the `Growable` variant, which relates to note 1 above.
|
||||||
// Alternatively, we might add `MaybeOwned` for the general case but
|
// Alternatively, we might add `MaybeOwned` for the general case but
|
||||||
|
|
|
@ -17,19 +17,19 @@
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback, PausableIdleCallback,
|
use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback};
|
||||||
Callback};
|
use std::rt::rtio::{PausableIdleCallback, Callback};
|
||||||
use std::unstable::sync::Exclusive;
|
use std::unstable::sync::Exclusive;
|
||||||
|
|
||||||
/// This is the only exported function from this module.
|
/// This is the only exported function from this module.
|
||||||
pub fn event_loop() -> ~EventLoop:Send {
|
pub fn event_loop() -> Box<EventLoop:Send> {
|
||||||
box BasicLoop::new() as ~EventLoop:Send
|
box BasicLoop::new() as Box<EventLoop:Send>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BasicLoop {
|
struct BasicLoop {
|
||||||
work: Vec<proc():Send>, // pending work
|
work: Vec<proc():Send>, // pending work
|
||||||
idle: Option<*mut BasicPausable>, // only one is allowed
|
idle: Option<*mut BasicPausable>, // only one is allowed
|
||||||
remotes: Vec<(uint, ~Callback:Send)>,
|
remotes: Vec<(uint, Box<Callback:Send>)>,
|
||||||
next_remote: uint,
|
next_remote: uint,
|
||||||
messages: Exclusive<Vec<Message>>,
|
messages: Exclusive<Vec<Message>>,
|
||||||
}
|
}
|
||||||
|
@ -140,23 +140,24 @@ impl EventLoop for BasicLoop {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Seems like a really weird requirement to have an event loop provide.
|
// FIXME: Seems like a really weird requirement to have an event loop provide.
|
||||||
fn pausable_idle_callback(&mut self, cb: ~Callback:Send)
|
fn pausable_idle_callback(&mut self, cb: Box<Callback:Send>)
|
||||||
-> ~PausableIdleCallback:Send
|
-> Box<PausableIdleCallback:Send> {
|
||||||
{
|
|
||||||
let callback = box BasicPausable::new(self, cb);
|
let callback = box BasicPausable::new(self, cb);
|
||||||
rtassert!(self.idle.is_none());
|
rtassert!(self.idle.is_none());
|
||||||
unsafe {
|
unsafe {
|
||||||
let cb_ptr: &*mut BasicPausable = cast::transmute(&callback);
|
let cb_ptr: &*mut BasicPausable = cast::transmute(&callback);
|
||||||
self.idle = Some(*cb_ptr);
|
self.idle = Some(*cb_ptr);
|
||||||
}
|
}
|
||||||
callback as ~PausableIdleCallback:Send
|
callback as Box<PausableIdleCallback:Send>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remote_callback(&mut self, f: ~Callback:Send) -> ~RemoteCallback:Send {
|
fn remote_callback(&mut self, f: Box<Callback:Send>)
|
||||||
|
-> Box<RemoteCallback:Send> {
|
||||||
let id = self.next_remote;
|
let id = self.next_remote;
|
||||||
self.next_remote += 1;
|
self.next_remote += 1;
|
||||||
self.remotes.push((id, f));
|
self.remotes.push((id, f));
|
||||||
box BasicRemote::new(self.messages.clone(), id) as ~RemoteCallback:Send
|
box BasicRemote::new(self.messages.clone(), id) as
|
||||||
|
Box<RemoteCallback:Send>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory> { None }
|
fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory> { None }
|
||||||
|
@ -197,12 +198,12 @@ impl Drop for BasicRemote {
|
||||||
|
|
||||||
struct BasicPausable {
|
struct BasicPausable {
|
||||||
eloop: *mut BasicLoop,
|
eloop: *mut BasicLoop,
|
||||||
work: ~Callback:Send,
|
work: Box<Callback:Send>,
|
||||||
active: bool,
|
active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BasicPausable {
|
impl BasicPausable {
|
||||||
fn new(eloop: &mut BasicLoop, cb: ~Callback:Send) -> BasicPausable {
|
fn new(eloop: &mut BasicLoop, cb: Box<Callback:Send>) -> BasicPausable {
|
||||||
BasicPausable {
|
BasicPausable {
|
||||||
active: false,
|
active: false,
|
||||||
work: cb,
|
work: cb,
|
||||||
|
|
|
@ -8,21 +8,21 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use stack::Stack;
|
||||||
use std::uint;
|
use std::uint;
|
||||||
use std::cast::{transmute, transmute_mut_unsafe};
|
use std::cast::{transmute, transmute_mut_unsafe};
|
||||||
use stack::Stack;
|
|
||||||
use std::rt::stack;
|
use std::rt::stack;
|
||||||
use std::raw;
|
use std::raw;
|
||||||
|
|
||||||
// FIXME #7761: Registers is boxed so that it is 16-byte aligned, for storing
|
// FIXME #7761: Registers is boxed so that it is 16-byte aligned, for storing
|
||||||
// SSE regs. It would be marginally better not to do this. In C++ we
|
// SSE regs. It would be marginally better not to do this. In C++ we
|
||||||
// use an attribute on a struct.
|
// use an attribute on a struct.
|
||||||
// FIXME #7761: It would be nice to define regs as `~Option<Registers>` since
|
// FIXME #7761: It would be nice to define regs as `Box<Option<Registers>>`
|
||||||
// the registers are sometimes empty, but the discriminant would
|
// since the registers are sometimes empty, but the discriminant would
|
||||||
// then misalign the regs again.
|
// then misalign the regs again.
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
/// Hold the registers while the task or scheduler is suspended
|
/// Hold the registers while the task or scheduler is suspended
|
||||||
regs: ~Registers,
|
regs: Box<Registers>,
|
||||||
/// Lower bound and upper bound for the stack
|
/// Lower bound and upper bound for the stack
|
||||||
stack_bounds: Option<(uint, uint)>,
|
stack_bounds: Option<(uint, uint)>,
|
||||||
}
|
}
|
||||||
|
@ -87,10 +87,10 @@ impl Context {
|
||||||
pub fn swap(out_context: &mut Context, in_context: &Context) {
|
pub fn swap(out_context: &mut Context, in_context: &Context) {
|
||||||
rtdebug!("swapping contexts");
|
rtdebug!("swapping contexts");
|
||||||
let out_regs: &mut Registers = match out_context {
|
let out_regs: &mut Registers = match out_context {
|
||||||
&Context { regs: ~ref mut r, .. } => r
|
&Context { regs: box ref mut r, .. } => r
|
||||||
};
|
};
|
||||||
let in_regs: &Registers = match in_context {
|
let in_regs: &Registers = match in_context {
|
||||||
&Context { regs: ~ref r, .. } => r
|
&Context { regs: box ref r, .. } => r
|
||||||
};
|
};
|
||||||
|
|
||||||
rtdebug!("noting the stack limit and doing raw swap");
|
rtdebug!("noting the stack limit and doing raw swap");
|
||||||
|
@ -151,7 +151,7 @@ struct Registers {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86")]
|
#[cfg(target_arch = "x86")]
|
||||||
fn new_regs() -> ~Registers {
|
fn new_regs() -> Box<Registers> {
|
||||||
box Registers {
|
box Registers {
|
||||||
eax: 0, ebx: 0, ecx: 0, edx: 0,
|
eax: 0, ebx: 0, ecx: 0, edx: 0,
|
||||||
ebp: 0, esi: 0, edi: 0, esp: 0,
|
ebp: 0, esi: 0, edi: 0, esp: 0,
|
||||||
|
@ -190,9 +190,9 @@ type Registers = [uint, ..34];
|
||||||
type Registers = [uint, ..22];
|
type Registers = [uint, ..22];
|
||||||
|
|
||||||
#[cfg(windows, target_arch = "x86_64")]
|
#[cfg(windows, target_arch = "x86_64")]
|
||||||
fn new_regs() -> ~Registers { box [0, .. 34] }
|
fn new_regs() -> Box<Registers> { box [0, .. 34] }
|
||||||
#[cfg(not(windows), target_arch = "x86_64")]
|
#[cfg(not(windows), target_arch = "x86_64")]
|
||||||
fn new_regs() -> ~Registers { box {let v = [0, .. 22]; v} }
|
fn new_regs() -> Box<Registers> { box {let v = [0, .. 22]; v} }
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
|
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
|
||||||
|
@ -241,7 +241,7 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
|
||||||
type Registers = [uint, ..32];
|
type Registers = [uint, ..32];
|
||||||
|
|
||||||
#[cfg(target_arch = "arm")]
|
#[cfg(target_arch = "arm")]
|
||||||
fn new_regs() -> ~Registers { box {[0, .. 32]} }
|
fn new_regs() -> Box<Registers> { box {[0, .. 32]} }
|
||||||
|
|
||||||
#[cfg(target_arch = "arm")]
|
#[cfg(target_arch = "arm")]
|
||||||
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
|
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
|
||||||
|
@ -270,7 +270,7 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
|
||||||
type Registers = [uint, ..32];
|
type Registers = [uint, ..32];
|
||||||
|
|
||||||
#[cfg(target_arch = "mips")]
|
#[cfg(target_arch = "mips")]
|
||||||
fn new_regs() -> ~Registers { box [0, .. 32] }
|
fn new_regs() -> Box<Registers> { box [0, .. 32] }
|
||||||
|
|
||||||
#[cfg(target_arch = "mips")]
|
#[cfg(target_arch = "mips")]
|
||||||
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
|
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
|
||||||
|
|
|
@ -288,7 +288,7 @@ macro_rules! green_start( ($f:ident) => (
|
||||||
/// The return value is used as the process return code. 0 on success, 101 on
|
/// The return value is used as the process return code. 0 on success, 101 on
|
||||||
/// error.
|
/// error.
|
||||||
pub fn start(argc: int, argv: **u8,
|
pub fn start(argc: int, argv: **u8,
|
||||||
event_loop_factory: fn() -> ~rtio::EventLoop:Send,
|
event_loop_factory: fn() -> Box<rtio::EventLoop:Send>,
|
||||||
main: proc():Send) -> int {
|
main: proc():Send) -> int {
|
||||||
rt::init(argc, argv);
|
rt::init(argc, argv);
|
||||||
let mut main = Some(main);
|
let mut main = Some(main);
|
||||||
|
@ -309,7 +309,7 @@ pub fn start(argc: int, argv: **u8,
|
||||||
///
|
///
|
||||||
/// This function will not return until all schedulers in the associated pool
|
/// This function will not return until all schedulers in the associated pool
|
||||||
/// have returned.
|
/// have returned.
|
||||||
pub fn run(event_loop_factory: fn() -> ~rtio::EventLoop:Send,
|
pub fn run(event_loop_factory: fn() -> Box<rtio::EventLoop:Send>,
|
||||||
main: proc():Send) -> int {
|
main: proc():Send) -> int {
|
||||||
// Create a scheduler pool and spawn the main task into this pool. We will
|
// Create a scheduler pool and spawn the main task into this pool. We will
|
||||||
// get notified over a channel when the main task exits.
|
// get notified over a channel when the main task exits.
|
||||||
|
@ -340,7 +340,7 @@ pub struct PoolConfig {
|
||||||
pub threads: uint,
|
pub threads: uint,
|
||||||
/// A factory function used to create new event loops. If this is not
|
/// A factory function used to create new event loops. If this is not
|
||||||
/// specified then the default event loop factory is used.
|
/// specified then the default event loop factory is used.
|
||||||
pub event_loop_factory: fn() -> ~rtio::EventLoop:Send,
|
pub event_loop_factory: fn() -> Box<rtio::EventLoop:Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PoolConfig {
|
impl PoolConfig {
|
||||||
|
@ -360,12 +360,12 @@ pub struct SchedPool {
|
||||||
id: uint,
|
id: uint,
|
||||||
threads: Vec<Thread<()>>,
|
threads: Vec<Thread<()>>,
|
||||||
handles: Vec<SchedHandle>,
|
handles: Vec<SchedHandle>,
|
||||||
stealers: Vec<deque::Stealer<~task::GreenTask>>,
|
stealers: Vec<deque::Stealer<Box<task::GreenTask>>>,
|
||||||
next_friend: uint,
|
next_friend: uint,
|
||||||
stack_pool: StackPool,
|
stack_pool: StackPool,
|
||||||
deque_pool: deque::BufferPool<~task::GreenTask>,
|
deque_pool: deque::BufferPool<Box<task::GreenTask>>,
|
||||||
sleepers: SleeperList,
|
sleepers: SleeperList,
|
||||||
factory: fn() -> ~rtio::EventLoop:Send,
|
factory: fn() -> Box<rtio::EventLoop:Send>,
|
||||||
task_state: TaskState,
|
task_state: TaskState,
|
||||||
tasks_done: Receiver<()>,
|
tasks_done: Receiver<()>,
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,7 @@ impl SchedPool {
|
||||||
/// This is useful to create a task which can then be sent to a specific
|
/// This is useful to create a task which can then be sent to a specific
|
||||||
/// scheduler created by `spawn_sched` (and possibly pin it to that
|
/// scheduler created by `spawn_sched` (and possibly pin it to that
|
||||||
/// scheduler).
|
/// scheduler).
|
||||||
pub fn task(&mut self, opts: TaskOpts, f: proc():Send) -> ~GreenTask {
|
pub fn task(&mut self, opts: TaskOpts, f: proc():Send) -> Box<GreenTask> {
|
||||||
GreenTask::configure(&mut self.stack_pool, opts, f)
|
GreenTask::configure(&mut self.stack_pool, opts, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,10 +46,10 @@ pub struct Scheduler {
|
||||||
/// inside this pool of schedulers
|
/// inside this pool of schedulers
|
||||||
pub task_state: TaskState,
|
pub task_state: TaskState,
|
||||||
/// There are N work queues, one per scheduler.
|
/// There are N work queues, one per scheduler.
|
||||||
work_queue: deque::Worker<~GreenTask>,
|
work_queue: deque::Worker<Box<GreenTask>>,
|
||||||
/// Work queues for the other schedulers. These are created by
|
/// Work queues for the other schedulers. These are created by
|
||||||
/// cloning the core work queues.
|
/// cloning the core work queues.
|
||||||
work_queues: Vec<deque::Stealer<~GreenTask>>,
|
work_queues: Vec<deque::Stealer<Box<GreenTask>>>,
|
||||||
/// The queue of incoming messages from other schedulers.
|
/// The queue of incoming messages from other schedulers.
|
||||||
/// These are enqueued by SchedHandles after which a remote callback
|
/// These are enqueued by SchedHandles after which a remote callback
|
||||||
/// is triggered to handle the message.
|
/// is triggered to handle the message.
|
||||||
|
@ -71,7 +71,7 @@ pub struct Scheduler {
|
||||||
no_sleep: bool,
|
no_sleep: bool,
|
||||||
/// The scheduler runs on a special task. When it is not running
|
/// The scheduler runs on a special task. When it is not running
|
||||||
/// it is stored here instead of the work queue.
|
/// it is stored here instead of the work queue.
|
||||||
sched_task: Option<~GreenTask>,
|
sched_task: Option<Box<GreenTask>>,
|
||||||
/// An action performed after a context switch on behalf of the
|
/// An action performed after a context switch on behalf of the
|
||||||
/// code running before the context switch
|
/// code running before the context switch
|
||||||
cleanup_job: Option<CleanupJob>,
|
cleanup_job: Option<CleanupJob>,
|
||||||
|
@ -83,7 +83,7 @@ pub struct Scheduler {
|
||||||
/// A fast XorShift rng for scheduler use
|
/// A fast XorShift rng for scheduler use
|
||||||
rng: XorShiftRng,
|
rng: XorShiftRng,
|
||||||
/// A togglable idle callback
|
/// A togglable idle callback
|
||||||
idle_callback: Option<~PausableIdleCallback:Send>,
|
idle_callback: Option<Box<PausableIdleCallback:Send>>,
|
||||||
/// A countdown that starts at a random value and is decremented
|
/// A countdown that starts at a random value and is decremented
|
||||||
/// every time a yield check is performed. When it hits 0 a task
|
/// every time a yield check is performed. When it hits 0 a task
|
||||||
/// will yield.
|
/// will yield.
|
||||||
|
@ -100,7 +100,7 @@ pub struct Scheduler {
|
||||||
// destroyed before it's actually destroyed.
|
// destroyed before it's actually destroyed.
|
||||||
|
|
||||||
/// The event loop used to drive the scheduler and perform I/O
|
/// The event loop used to drive the scheduler and perform I/O
|
||||||
pub event_loop: ~EventLoop:Send,
|
pub event_loop: Box<EventLoop:Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An indication of how hard to work on a given operation, the difference
|
/// An indication of how hard to work on a given operation, the difference
|
||||||
|
@ -123,9 +123,9 @@ impl Scheduler {
|
||||||
// * Initialization Functions
|
// * Initialization Functions
|
||||||
|
|
||||||
pub fn new(pool_id: uint,
|
pub fn new(pool_id: uint,
|
||||||
event_loop: ~EventLoop:Send,
|
event_loop: Box<EventLoop:Send>,
|
||||||
work_queue: deque::Worker<~GreenTask>,
|
work_queue: deque::Worker<Box<GreenTask>>,
|
||||||
work_queues: Vec<deque::Stealer<~GreenTask>>,
|
work_queues: Vec<deque::Stealer<Box<GreenTask>>>,
|
||||||
sleeper_list: SleeperList,
|
sleeper_list: SleeperList,
|
||||||
state: TaskState)
|
state: TaskState)
|
||||||
-> Scheduler {
|
-> Scheduler {
|
||||||
|
@ -136,9 +136,9 @@ impl Scheduler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_special(pool_id: uint,
|
pub fn new_special(pool_id: uint,
|
||||||
event_loop: ~EventLoop:Send,
|
event_loop: Box<EventLoop:Send>,
|
||||||
work_queue: deque::Worker<~GreenTask>,
|
work_queue: deque::Worker<Box<GreenTask>>,
|
||||||
work_queues: Vec<deque::Stealer<~GreenTask>>,
|
work_queues: Vec<deque::Stealer<Box<GreenTask>>>,
|
||||||
sleeper_list: SleeperList,
|
sleeper_list: SleeperList,
|
||||||
run_anything: bool,
|
run_anything: bool,
|
||||||
friend: Option<SchedHandle>,
|
friend: Option<SchedHandle>,
|
||||||
|
@ -183,7 +183,7 @@ impl Scheduler {
|
||||||
pub fn bootstrap(mut ~self) {
|
pub fn bootstrap(mut ~self) {
|
||||||
|
|
||||||
// Build an Idle callback.
|
// Build an Idle callback.
|
||||||
let cb = box SchedRunner as ~Callback:Send;
|
let cb = box SchedRunner as Box<Callback:Send>;
|
||||||
self.idle_callback = Some(self.event_loop.pausable_idle_callback(cb));
|
self.idle_callback = Some(self.event_loop.pausable_idle_callback(cb));
|
||||||
|
|
||||||
// Create a task for the scheduler with an empty context.
|
// Create a task for the scheduler with an empty context.
|
||||||
|
@ -224,14 +224,14 @@ impl Scheduler {
|
||||||
|
|
||||||
// This does not return a scheduler, as the scheduler is placed
|
// This does not return a scheduler, as the scheduler is placed
|
||||||
// inside the task.
|
// inside the task.
|
||||||
pub fn run(mut ~self, stask: ~GreenTask) -> ~GreenTask {
|
pub fn run(mut ~self, stask: Box<GreenTask>) -> Box<GreenTask> {
|
||||||
|
|
||||||
// This is unsafe because we need to place the scheduler, with
|
// This is unsafe because we need to place the scheduler, with
|
||||||
// the event_loop inside, inside our task. But we still need a
|
// the event_loop inside, inside our task. But we still need a
|
||||||
// mutable reference to the event_loop to give it the "run"
|
// mutable reference to the event_loop to give it the "run"
|
||||||
// command.
|
// command.
|
||||||
unsafe {
|
unsafe {
|
||||||
let event_loop: *mut ~EventLoop:Send = &mut self.event_loop;
|
let event_loop: *mut Box<EventLoop:Send> = &mut self.event_loop;
|
||||||
// Our scheduler must be in the task before the event loop
|
// Our scheduler must be in the task before the event loop
|
||||||
// is started.
|
// is started.
|
||||||
stask.put_with_sched(self);
|
stask.put_with_sched(self);
|
||||||
|
@ -271,7 +271,7 @@ impl Scheduler {
|
||||||
// If we try really hard to do some work, but no work is available to be
|
// If we try really hard to do some work, but no work is available to be
|
||||||
// done, then we fall back to epoll() to block this thread waiting for more
|
// done, then we fall back to epoll() to block this thread waiting for more
|
||||||
// work (instead of busy waiting).
|
// work (instead of busy waiting).
|
||||||
fn run_sched_once(mut ~self, stask: ~GreenTask) {
|
fn run_sched_once(mut ~self, stask: Box<GreenTask>) {
|
||||||
// Make sure that we're not lying in that the `stask` argument is indeed
|
// Make sure that we're not lying in that the `stask` argument is indeed
|
||||||
// the scheduler task for this scheduler.
|
// the scheduler task for this scheduler.
|
||||||
assert!(self.sched_task.is_none());
|
assert!(self.sched_task.is_none());
|
||||||
|
@ -349,9 +349,9 @@ impl Scheduler {
|
||||||
// returns the still-available scheduler. At this point all
|
// returns the still-available scheduler. At this point all
|
||||||
// message-handling will count as a turn of work, and as a result
|
// message-handling will count as a turn of work, and as a result
|
||||||
// return None.
|
// return None.
|
||||||
fn interpret_message_queue(mut ~self, stask: ~GreenTask,
|
fn interpret_message_queue(mut ~self, stask: Box<GreenTask>,
|
||||||
effort: EffortLevel)
|
effort: EffortLevel)
|
||||||
-> (~Scheduler, ~GreenTask, bool)
|
-> (Box<Scheduler>, Box<GreenTask>, bool)
|
||||||
{
|
{
|
||||||
|
|
||||||
let msg = if effort == DontTryTooHard {
|
let msg = if effort == DontTryTooHard {
|
||||||
|
@ -432,8 +432,8 @@ impl Scheduler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_work(mut ~self,
|
fn do_work(mut ~self, stask: Box<GreenTask>)
|
||||||
stask: ~GreenTask) -> (~Scheduler, ~GreenTask, bool) {
|
-> (Box<Scheduler>, Box<GreenTask>, bool) {
|
||||||
rtdebug!("scheduler calling do work");
|
rtdebug!("scheduler calling do work");
|
||||||
match self.find_work() {
|
match self.find_work() {
|
||||||
Some(task) => {
|
Some(task) => {
|
||||||
|
@ -459,7 +459,7 @@ impl Scheduler {
|
||||||
// First step in the process is to find a task. This function does
|
// First step in the process is to find a task. This function does
|
||||||
// that by first checking the local queue, and if there is no work
|
// that by first checking the local queue, and if there is no work
|
||||||
// there, trying to steal from the remote work queues.
|
// there, trying to steal from the remote work queues.
|
||||||
fn find_work(&mut self) -> Option<~GreenTask> {
|
fn find_work(&mut self) -> Option<Box<GreenTask>> {
|
||||||
rtdebug!("scheduler looking for work");
|
rtdebug!("scheduler looking for work");
|
||||||
if !self.steal_for_yield {
|
if !self.steal_for_yield {
|
||||||
match self.work_queue.pop() {
|
match self.work_queue.pop() {
|
||||||
|
@ -497,7 +497,7 @@ impl Scheduler {
|
||||||
// Try stealing from all queues the scheduler knows about. This
|
// Try stealing from all queues the scheduler knows about. This
|
||||||
// naive implementation can steal from our own queue or from other
|
// naive implementation can steal from our own queue or from other
|
||||||
// special schedulers.
|
// special schedulers.
|
||||||
fn try_steals(&mut self) -> Option<~GreenTask> {
|
fn try_steals(&mut self) -> Option<Box<GreenTask>> {
|
||||||
let work_queues = &mut self.work_queues;
|
let work_queues = &mut self.work_queues;
|
||||||
let len = work_queues.len();
|
let len = work_queues.len();
|
||||||
let start_index = self.rng.gen_range(0, len);
|
let start_index = self.rng.gen_range(0, len);
|
||||||
|
@ -517,9 +517,11 @@ impl Scheduler {
|
||||||
// * Task Routing Functions - Make sure tasks send up in the right
|
// * Task Routing Functions - Make sure tasks send up in the right
|
||||||
// place.
|
// place.
|
||||||
|
|
||||||
fn process_task(mut ~self, cur: ~GreenTask,
|
fn process_task(mut ~self,
|
||||||
mut next: ~GreenTask,
|
cur: Box<GreenTask>,
|
||||||
schedule_fn: SchedulingFn) -> (~Scheduler, ~GreenTask) {
|
mut next: Box<GreenTask>,
|
||||||
|
schedule_fn: SchedulingFn)
|
||||||
|
-> (Box<Scheduler>, Box<GreenTask>) {
|
||||||
rtdebug!("processing a task");
|
rtdebug!("processing a task");
|
||||||
|
|
||||||
match next.take_unwrap_home() {
|
match next.take_unwrap_home() {
|
||||||
|
@ -549,7 +551,7 @@ impl Scheduler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_task_home(task: ~GreenTask) {
|
fn send_task_home(task: Box<GreenTask>) {
|
||||||
let mut task = task;
|
let mut task = task;
|
||||||
match task.take_unwrap_home() {
|
match task.take_unwrap_home() {
|
||||||
HomeSched(mut home_handle) => home_handle.send(PinnedTask(task)),
|
HomeSched(mut home_handle) => home_handle.send(PinnedTask(task)),
|
||||||
|
@ -559,7 +561,7 @@ impl Scheduler {
|
||||||
|
|
||||||
/// Take a non-homed task we aren't allowed to run here and send
|
/// Take a non-homed task we aren't allowed to run here and send
|
||||||
/// it to the designated friend scheduler to execute.
|
/// it to the designated friend scheduler to execute.
|
||||||
fn send_to_friend(&mut self, task: ~GreenTask) {
|
fn send_to_friend(&mut self, task: Box<GreenTask>) {
|
||||||
rtdebug!("sending a task to friend");
|
rtdebug!("sending a task to friend");
|
||||||
match self.friend_handle {
|
match self.friend_handle {
|
||||||
Some(ref mut handle) => {
|
Some(ref mut handle) => {
|
||||||
|
@ -576,7 +578,7 @@ impl Scheduler {
|
||||||
/// Pushes the task onto the work stealing queue and tells the
|
/// Pushes the task onto the work stealing queue and tells the
|
||||||
/// event loop to run it later. Always use this instead of pushing
|
/// event loop to run it later. Always use this instead of pushing
|
||||||
/// to the work queue directly.
|
/// to the work queue directly.
|
||||||
pub fn enqueue_task(&mut self, task: ~GreenTask) {
|
pub fn enqueue_task(&mut self, task: Box<GreenTask>) {
|
||||||
|
|
||||||
// We push the task onto our local queue clone.
|
// We push the task onto our local queue clone.
|
||||||
assert!(!task.is_sched());
|
assert!(!task.is_sched());
|
||||||
|
@ -609,9 +611,10 @@ impl Scheduler {
|
||||||
// old task as inputs.
|
// old task as inputs.
|
||||||
|
|
||||||
pub fn change_task_context(mut ~self,
|
pub fn change_task_context(mut ~self,
|
||||||
current_task: ~GreenTask,
|
current_task: Box<GreenTask>,
|
||||||
mut next_task: ~GreenTask,
|
mut next_task: Box<GreenTask>,
|
||||||
f: |&mut Scheduler, ~GreenTask|) -> ~GreenTask {
|
f: |&mut Scheduler, Box<GreenTask>|)
|
||||||
|
-> Box<GreenTask> {
|
||||||
let f_opaque = ClosureConverter::from_fn(f);
|
let f_opaque = ClosureConverter::from_fn(f);
|
||||||
|
|
||||||
let current_task_dupe = &*current_task as *GreenTask;
|
let current_task_dupe = &*current_task as *GreenTask;
|
||||||
|
@ -655,7 +658,7 @@ impl Scheduler {
|
||||||
// When the context swaps back to this task we immediately
|
// When the context swaps back to this task we immediately
|
||||||
// run the cleanup job, as expected by the previously called
|
// run the cleanup job, as expected by the previously called
|
||||||
// swap_contexts function.
|
// swap_contexts function.
|
||||||
let mut current_task: ~GreenTask = unsafe {
|
let mut current_task: Box<GreenTask> = unsafe {
|
||||||
cast::transmute(current_task_dupe)
|
cast::transmute(current_task_dupe)
|
||||||
};
|
};
|
||||||
current_task.sched.get_mut_ref().run_cleanup_job();
|
current_task.sched.get_mut_ref().run_cleanup_job();
|
||||||
|
@ -688,8 +691,10 @@ impl Scheduler {
|
||||||
|
|
||||||
// * Context Swapping Helpers - Here be ugliness!
|
// * Context Swapping Helpers - Here be ugliness!
|
||||||
|
|
||||||
pub fn resume_task_immediately(~self, cur: ~GreenTask,
|
pub fn resume_task_immediately(~self,
|
||||||
next: ~GreenTask) -> (~Scheduler, ~GreenTask) {
|
cur: Box<GreenTask>,
|
||||||
|
next: Box<GreenTask>)
|
||||||
|
-> (Box<Scheduler>, Box<GreenTask>) {
|
||||||
assert!(cur.is_sched());
|
assert!(cur.is_sched());
|
||||||
let mut cur = self.change_task_context(cur, next, |sched, stask| {
|
let mut cur = self.change_task_context(cur, next, |sched, stask| {
|
||||||
assert!(sched.sched_task.is_none());
|
assert!(sched.sched_task.is_none());
|
||||||
|
@ -698,9 +703,10 @@ impl Scheduler {
|
||||||
(cur.sched.take_unwrap(), cur)
|
(cur.sched.take_unwrap(), cur)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resume_task_immediately_cl(sched: ~Scheduler,
|
fn resume_task_immediately_cl(sched: Box<Scheduler>,
|
||||||
cur: ~GreenTask,
|
cur: Box<GreenTask>,
|
||||||
next: ~GreenTask) -> (~Scheduler, ~GreenTask) {
|
next: Box<GreenTask>)
|
||||||
|
-> (Box<Scheduler>, Box<GreenTask>) {
|
||||||
sched.resume_task_immediately(cur, next)
|
sched.resume_task_immediately(cur, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,7 +732,7 @@ impl Scheduler {
|
||||||
/// guaranteed that this function will not return before the given closure
|
/// guaranteed that this function will not return before the given closure
|
||||||
/// has returned.
|
/// has returned.
|
||||||
pub fn deschedule_running_task_and_then(mut ~self,
|
pub fn deschedule_running_task_and_then(mut ~self,
|
||||||
cur: ~GreenTask,
|
cur: Box<GreenTask>,
|
||||||
f: |&mut Scheduler, BlockedTask|) {
|
f: |&mut Scheduler, BlockedTask|) {
|
||||||
// Trickier - we need to get the scheduler task out of self
|
// Trickier - we need to get the scheduler task out of self
|
||||||
// and use it as the destination.
|
// and use it as the destination.
|
||||||
|
@ -736,8 +742,8 @@ impl Scheduler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn switch_running_tasks_and_then(~self,
|
pub fn switch_running_tasks_and_then(~self,
|
||||||
cur: ~GreenTask,
|
cur: Box<GreenTask>,
|
||||||
next: ~GreenTask,
|
next: Box<GreenTask>,
|
||||||
f: |&mut Scheduler, BlockedTask|) {
|
f: |&mut Scheduler, BlockedTask|) {
|
||||||
// And here comes one of the sad moments in which a lock is used in a
|
// And here comes one of the sad moments in which a lock is used in a
|
||||||
// core portion of the rust runtime. As always, this is highly
|
// core portion of the rust runtime. As always, this is highly
|
||||||
|
@ -768,8 +774,10 @@ impl Scheduler {
|
||||||
cur.put();
|
cur.put();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch_task(sched: ~Scheduler, cur: ~GreenTask,
|
fn switch_task(sched: Box<Scheduler>,
|
||||||
next: ~GreenTask) -> (~Scheduler, ~GreenTask) {
|
cur: Box<GreenTask>,
|
||||||
|
next: Box<GreenTask>)
|
||||||
|
-> (Box<Scheduler>, Box<GreenTask>) {
|
||||||
let mut cur = sched.change_task_context(cur, next, |sched, last_task| {
|
let mut cur = sched.change_task_context(cur, next, |sched, last_task| {
|
||||||
if last_task.is_sched() {
|
if last_task.is_sched() {
|
||||||
assert!(sched.sched_task.is_none());
|
assert!(sched.sched_task.is_none());
|
||||||
|
@ -785,7 +793,7 @@ impl Scheduler {
|
||||||
|
|
||||||
/// Called by a running task to end execution, after which it will
|
/// Called by a running task to end execution, after which it will
|
||||||
/// be recycled by the scheduler for reuse in a new task.
|
/// be recycled by the scheduler for reuse in a new task.
|
||||||
pub fn terminate_current_task(mut ~self, cur: ~GreenTask) -> ! {
|
pub fn terminate_current_task(mut ~self, cur: Box<GreenTask>) -> ! {
|
||||||
// Similar to deschedule running task and then, but cannot go through
|
// Similar to deschedule running task and then, but cannot go through
|
||||||
// the task-blocking path. The task is already dying.
|
// the task-blocking path. The task is already dying.
|
||||||
let stask = self.sched_task.take_unwrap();
|
let stask = self.sched_task.take_unwrap();
|
||||||
|
@ -797,13 +805,13 @@ impl Scheduler {
|
||||||
fail!("should never return!");
|
fail!("should never return!");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_task(~self, cur: ~GreenTask, next: ~GreenTask) {
|
pub fn run_task(~self, cur: Box<GreenTask>, next: Box<GreenTask>) {
|
||||||
let (sched, task) =
|
let (sched, task) =
|
||||||
self.process_task(cur, next, Scheduler::switch_task);
|
self.process_task(cur, next, Scheduler::switch_task);
|
||||||
task.put_with_sched(sched);
|
task.put_with_sched(sched);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_task_later(mut cur: ~GreenTask, next: ~GreenTask) {
|
pub fn run_task_later(mut cur: Box<GreenTask>, next: Box<GreenTask>) {
|
||||||
let mut sched = cur.sched.take_unwrap();
|
let mut sched = cur.sched.take_unwrap();
|
||||||
sched.enqueue_task(next);
|
sched.enqueue_task(next);
|
||||||
cur.put_with_sched(sched);
|
cur.put_with_sched(sched);
|
||||||
|
@ -813,7 +821,7 @@ impl Scheduler {
|
||||||
/// to introduce some amount of randomness to the scheduler. Currently the
|
/// to introduce some amount of randomness to the scheduler. Currently the
|
||||||
/// randomness is a result of performing a round of work stealing (which
|
/// randomness is a result of performing a round of work stealing (which
|
||||||
/// may end up stealing from the current scheduler).
|
/// may end up stealing from the current scheduler).
|
||||||
pub fn yield_now(mut ~self, cur: ~GreenTask) {
|
pub fn yield_now(mut ~self, cur: Box<GreenTask>) {
|
||||||
// Async handles trigger the scheduler by calling yield_now on the local
|
// Async handles trigger the scheduler by calling yield_now on the local
|
||||||
// task, which eventually gets us to here. See comments in SchedRunner
|
// task, which eventually gets us to here. See comments in SchedRunner
|
||||||
// for more info on this.
|
// for more info on this.
|
||||||
|
@ -832,7 +840,7 @@ impl Scheduler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_yield(mut ~self, cur: ~GreenTask) {
|
pub fn maybe_yield(mut ~self, cur: Box<GreenTask>) {
|
||||||
// It's possible for sched tasks to possibly call this function, and it
|
// It's possible for sched tasks to possibly call this function, and it
|
||||||
// just means that they're likely sending on channels (which
|
// just means that they're likely sending on channels (which
|
||||||
// occasionally call this function). Sched tasks follow different paths
|
// occasionally call this function). Sched tasks follow different paths
|
||||||
|
@ -881,20 +889,20 @@ impl Scheduler {
|
||||||
|
|
||||||
// Supporting types
|
// Supporting types
|
||||||
|
|
||||||
type SchedulingFn = fn (~Scheduler, ~GreenTask, ~GreenTask)
|
type SchedulingFn = fn(Box<Scheduler>, Box<GreenTask>, Box<GreenTask>)
|
||||||
-> (~Scheduler, ~GreenTask);
|
-> (Box<Scheduler>, Box<GreenTask>);
|
||||||
|
|
||||||
pub enum SchedMessage {
|
pub enum SchedMessage {
|
||||||
Wake,
|
Wake,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
NewNeighbor(deque::Stealer<~GreenTask>),
|
NewNeighbor(deque::Stealer<Box<GreenTask>>),
|
||||||
PinnedTask(~GreenTask),
|
PinnedTask(Box<GreenTask>),
|
||||||
TaskFromFriend(~GreenTask),
|
TaskFromFriend(Box<GreenTask>),
|
||||||
RunOnce(~GreenTask),
|
RunOnce(Box<GreenTask>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SchedHandle {
|
pub struct SchedHandle {
|
||||||
remote: ~RemoteCallback:Send,
|
remote: Box<RemoteCallback:Send>,
|
||||||
queue: msgq::Producer<SchedMessage>,
|
queue: msgq::Producer<SchedMessage>,
|
||||||
pub sched_id: uint
|
pub sched_id: uint
|
||||||
}
|
}
|
||||||
|
@ -920,18 +928,18 @@ impl Callback for SchedRunner {
|
||||||
// This function could be converted to `GreenTask::convert` if
|
// This function could be converted to `GreenTask::convert` if
|
||||||
// absolutely necessary, but for cleanliness it is much better to not
|
// absolutely necessary, but for cleanliness it is much better to not
|
||||||
// use the conversion function.
|
// use the conversion function.
|
||||||
let task: ~Task = Local::take();
|
let task: Box<Task> = Local::take();
|
||||||
task.yield_now();
|
task.yield_now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CleanupJob {
|
struct CleanupJob {
|
||||||
task: ~GreenTask,
|
task: Box<GreenTask>,
|
||||||
f: UnsafeTaskReceiver
|
f: UnsafeTaskReceiver
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CleanupJob {
|
impl CleanupJob {
|
||||||
pub fn new(task: ~GreenTask, f: UnsafeTaskReceiver) -> CleanupJob {
|
pub fn new(task: Box<GreenTask>, f: UnsafeTaskReceiver) -> CleanupJob {
|
||||||
CleanupJob {
|
CleanupJob {
|
||||||
task: task,
|
task: task,
|
||||||
f: f
|
f: f
|
||||||
|
@ -948,14 +956,14 @@ impl CleanupJob {
|
||||||
// complaining
|
// complaining
|
||||||
type UnsafeTaskReceiver = raw::Closure;
|
type UnsafeTaskReceiver = raw::Closure;
|
||||||
trait ClosureConverter {
|
trait ClosureConverter {
|
||||||
fn from_fn(|&mut Scheduler, ~GreenTask|) -> Self;
|
fn from_fn(|&mut Scheduler, Box<GreenTask>|) -> Self;
|
||||||
fn to_fn(self) -> |&mut Scheduler, ~GreenTask|;
|
fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>|;
|
||||||
}
|
}
|
||||||
impl ClosureConverter for UnsafeTaskReceiver {
|
impl ClosureConverter for UnsafeTaskReceiver {
|
||||||
fn from_fn(f: |&mut Scheduler, ~GreenTask|) -> UnsafeTaskReceiver {
|
fn from_fn(f: |&mut Scheduler, Box<GreenTask>|) -> UnsafeTaskReceiver {
|
||||||
unsafe { cast::transmute(f) }
|
unsafe { cast::transmute(f) }
|
||||||
}
|
}
|
||||||
fn to_fn(self) -> |&mut Scheduler, ~GreenTask| {
|
fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>| {
|
||||||
unsafe { cast::transmute(self) }
|
unsafe { cast::transmute(self) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1218,7 +1226,7 @@ mod test {
|
||||||
// Signal from the special task that we are done.
|
// Signal from the special task that we are done.
|
||||||
let (tx, rx) = channel::<()>();
|
let (tx, rx) = channel::<()>();
|
||||||
|
|
||||||
fn run(next: ~GreenTask) {
|
fn run(next: Box<GreenTask>) {
|
||||||
let mut task = GreenTask::convert(Local::take());
|
let mut task = GreenTask::convert(Local::take());
|
||||||
let sched = task.sched.take_unwrap();
|
let sched = task.sched.take_unwrap();
|
||||||
sched.run_task(task, next)
|
sched.run_task(task, next)
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct SimpleTask {
|
||||||
impl Runtime for SimpleTask {
|
impl Runtime for SimpleTask {
|
||||||
// Implement the simple tasks of descheduling and rescheduling, but only in
|
// Implement the simple tasks of descheduling and rescheduling, but only in
|
||||||
// a simple number of cases.
|
// a simple number of cases.
|
||||||
fn deschedule(mut ~self, times: uint, mut cur_task: ~Task,
|
fn deschedule(mut ~self, times: uint, mut cur_task: Box<Task>,
|
||||||
f: |BlockedTask| -> Result<(), BlockedTask>) {
|
f: |BlockedTask| -> Result<(), BlockedTask>) {
|
||||||
assert!(times == 1);
|
assert!(times == 1);
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ impl Runtime for SimpleTask {
|
||||||
}
|
}
|
||||||
Local::put(cur_task);
|
Local::put(cur_task);
|
||||||
}
|
}
|
||||||
fn reawaken(mut ~self, mut to_wake: ~Task) {
|
fn reawaken(mut ~self, mut to_wake: Box<Task>) {
|
||||||
let me = &mut *self as *mut SimpleTask;
|
let me = &mut *self as *mut SimpleTask;
|
||||||
to_wake.put_runtime(self);
|
to_wake.put_runtime(self);
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -70,18 +70,21 @@ impl Runtime for SimpleTask {
|
||||||
// purpose. A "simple task" is just that, a very simple task that can't
|
// purpose. A "simple task" is just that, a very simple task that can't
|
||||||
// really do a whole lot. The only purpose of the task is to get us off our
|
// really do a whole lot. The only purpose of the task is to get us off our
|
||||||
// feet and running.
|
// feet and running.
|
||||||
fn yield_now(~self, _cur_task: ~Task) { fail!() }
|
fn yield_now(~self, _cur_task: Box<Task>) { fail!() }
|
||||||
fn maybe_yield(~self, _cur_task: ~Task) { fail!() }
|
fn maybe_yield(~self, _cur_task: Box<Task>) { fail!() }
|
||||||
fn spawn_sibling(~self, _cur_task: ~Task, _opts: TaskOpts, _f: proc():Send) {
|
fn spawn_sibling(~self,
|
||||||
|
_cur_task: Box<Task>,
|
||||||
|
_opts: TaskOpts,
|
||||||
|
_f: proc():Send) {
|
||||||
fail!()
|
fail!()
|
||||||
}
|
}
|
||||||
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
|
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
|
||||||
fn stack_bounds(&self) -> (uint, uint) { fail!() }
|
fn stack_bounds(&self) -> (uint, uint) { fail!() }
|
||||||
fn can_block(&self) -> bool { true }
|
fn can_block(&self) -> bool { true }
|
||||||
fn wrap(~self) -> ~Any { fail!() }
|
fn wrap(~self) -> Box<Any> { fail!() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task() -> ~Task {
|
pub fn task() -> Box<Task> {
|
||||||
let mut task = box Task::new();
|
let mut task = box Task::new();
|
||||||
task.put_runtime(box SimpleTask {
|
task.put_runtime(box SimpleTask {
|
||||||
lock: unsafe {NativeMutex::new()},
|
lock: unsafe {NativeMutex::new()},
|
||||||
|
|
|
@ -50,12 +50,12 @@ pub struct GreenTask {
|
||||||
|
|
||||||
/// Slot for maintaining ownership of a scheduler. If a task is running,
|
/// Slot for maintaining ownership of a scheduler. If a task is running,
|
||||||
/// this value will be Some(sched) where the task is running on "sched".
|
/// this value will be Some(sched) where the task is running on "sched".
|
||||||
pub sched: Option<~Scheduler>,
|
pub sched: Option<Box<Scheduler>>,
|
||||||
|
|
||||||
/// Temporary ownership slot of a std::rt::task::Task object. This is used
|
/// Temporary ownership slot of a std::rt::task::Task object. This is used
|
||||||
/// to squirrel that libstd task away while we're performing green task
|
/// to squirrel that libstd task away while we're performing green task
|
||||||
/// operations.
|
/// operations.
|
||||||
pub task: Option<~Task>,
|
pub task: Option<Box<Task>>,
|
||||||
|
|
||||||
/// Dictates whether this is a sched task or a normal green task
|
/// Dictates whether this is a sched task or a normal green task
|
||||||
pub task_type: TaskType,
|
pub task_type: TaskType,
|
||||||
|
@ -85,8 +85,8 @@ pub enum Home {
|
||||||
/// for all green tasks. This code is actually called after the initial context
|
/// for all green tasks. This code is actually called after the initial context
|
||||||
/// switch onto a green thread.
|
/// switch onto a green thread.
|
||||||
///
|
///
|
||||||
/// The first argument to this function is the `~GreenTask` pointer, and the
|
/// The first argument to this function is the `Box<GreenTask>` pointer, and
|
||||||
/// next two arguments are the user-provided procedure for running code.
|
/// the next two arguments are the user-provided procedure for running code.
|
||||||
///
|
///
|
||||||
/// The goal for having this weird-looking function is to reduce the number of
|
/// The goal for having this weird-looking function is to reduce the number of
|
||||||
/// allocations done on a green-task startup as much as possible.
|
/// allocations done on a green-task startup as much as possible.
|
||||||
|
@ -96,8 +96,8 @@ extern fn bootstrap_green_task(task: uint, code: *(), env: *()) -> ! {
|
||||||
cast::transmute(raw::Procedure { code: code, env: env })
|
cast::transmute(raw::Procedure { code: code, env: env })
|
||||||
};
|
};
|
||||||
|
|
||||||
// Acquire ownership of the `~GreenTask`
|
// Acquire ownership of the `Box<GreenTask>`
|
||||||
let mut task: ~GreenTask = unsafe { cast::transmute(task) };
|
let mut task: Box<GreenTask> = unsafe { cast::transmute(task) };
|
||||||
|
|
||||||
// First code after swap to this new context. Run our cleanup job
|
// First code after swap to this new context. Run our cleanup job
|
||||||
task.pool_id = {
|
task.pool_id = {
|
||||||
|
@ -129,7 +129,7 @@ impl GreenTask {
|
||||||
/// and will not have any contained Task structure.
|
/// and will not have any contained Task structure.
|
||||||
pub fn new(stack_pool: &mut StackPool,
|
pub fn new(stack_pool: &mut StackPool,
|
||||||
stack_size: Option<uint>,
|
stack_size: Option<uint>,
|
||||||
start: proc():Send) -> ~GreenTask {
|
start: proc():Send) -> Box<GreenTask> {
|
||||||
GreenTask::new_homed(stack_pool, stack_size, AnySched, start)
|
GreenTask::new_homed(stack_pool, stack_size, AnySched, start)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ impl GreenTask {
|
||||||
pub fn new_homed(stack_pool: &mut StackPool,
|
pub fn new_homed(stack_pool: &mut StackPool,
|
||||||
stack_size: Option<uint>,
|
stack_size: Option<uint>,
|
||||||
home: Home,
|
home: Home,
|
||||||
start: proc():Send) -> ~GreenTask {
|
start: proc():Send) -> Box<GreenTask> {
|
||||||
// Allocate ourselves a GreenTask structure
|
// Allocate ourselves a GreenTask structure
|
||||||
let mut ops = GreenTask::new_typed(None, TypeGreen(Some(home)));
|
let mut ops = GreenTask::new_typed(None, TypeGreen(Some(home)));
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ impl GreenTask {
|
||||||
/// Creates a new green task with the specified coroutine and type, this is
|
/// Creates a new green task with the specified coroutine and type, this is
|
||||||
/// useful when creating scheduler tasks.
|
/// useful when creating scheduler tasks.
|
||||||
pub fn new_typed(coroutine: Option<Coroutine>,
|
pub fn new_typed(coroutine: Option<Coroutine>,
|
||||||
task_type: TaskType) -> ~GreenTask {
|
task_type: TaskType) -> Box<GreenTask> {
|
||||||
box GreenTask {
|
box GreenTask {
|
||||||
pool_id: 0,
|
pool_id: 0,
|
||||||
coroutine: coroutine,
|
coroutine: coroutine,
|
||||||
|
@ -175,7 +175,7 @@ impl GreenTask {
|
||||||
/// new stack for this task.
|
/// new stack for this task.
|
||||||
pub fn configure(pool: &mut StackPool,
|
pub fn configure(pool: &mut StackPool,
|
||||||
opts: TaskOpts,
|
opts: TaskOpts,
|
||||||
f: proc():Send) -> ~GreenTask {
|
f: proc():Send) -> Box<GreenTask> {
|
||||||
let TaskOpts {
|
let TaskOpts {
|
||||||
notify_chan, name, stack_size,
|
notify_chan, name, stack_size,
|
||||||
stderr, stdout,
|
stderr, stdout,
|
||||||
|
@ -204,7 +204,7 @@ impl GreenTask {
|
||||||
///
|
///
|
||||||
/// This function will assert that the task is indeed a green task before
|
/// This function will assert that the task is indeed a green task before
|
||||||
/// returning (and will kill the entire process if this is wrong).
|
/// returning (and will kill the entire process if this is wrong).
|
||||||
pub fn convert(mut task: ~Task) -> ~GreenTask {
|
pub fn convert(mut task: Box<Task>) -> Box<GreenTask> {
|
||||||
match task.maybe_take_runtime::<GreenTask>() {
|
match task.maybe_take_runtime::<GreenTask>() {
|
||||||
Some(mut green) => {
|
Some(mut green) => {
|
||||||
green.put_task(task);
|
green.put_task(task);
|
||||||
|
@ -270,22 +270,24 @@ impl GreenTask {
|
||||||
self as *GreenTask as uint
|
self as *GreenTask as uint
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn from_uint(val: uint) -> ~GreenTask { cast::transmute(val) }
|
pub unsafe fn from_uint(val: uint) -> Box<GreenTask> {
|
||||||
|
cast::transmute(val)
|
||||||
|
}
|
||||||
|
|
||||||
// Runtime glue functions and helpers
|
// Runtime glue functions and helpers
|
||||||
|
|
||||||
pub fn put_with_sched(mut ~self, sched: ~Scheduler) {
|
pub fn put_with_sched(mut ~self, sched: Box<Scheduler>) {
|
||||||
assert!(self.sched.is_none());
|
assert!(self.sched.is_none());
|
||||||
self.sched = Some(sched);
|
self.sched = Some(sched);
|
||||||
self.put();
|
self.put();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put_task(&mut self, task: ~Task) {
|
pub fn put_task(&mut self, task: Box<Task>) {
|
||||||
assert!(self.task.is_none());
|
assert!(self.task.is_none());
|
||||||
self.task = Some(task);
|
self.task = Some(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn swap(mut ~self) -> ~Task {
|
pub fn swap(mut ~self) -> Box<Task> {
|
||||||
let mut task = self.task.take_unwrap();
|
let mut task = self.task.take_unwrap();
|
||||||
task.put_runtime(self);
|
task.put_runtime(self);
|
||||||
return task;
|
return task;
|
||||||
|
@ -331,19 +333,19 @@ impl GreenTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Runtime for GreenTask {
|
impl Runtime for GreenTask {
|
||||||
fn yield_now(mut ~self, cur_task: ~Task) {
|
fn yield_now(mut ~self, cur_task: Box<Task>) {
|
||||||
self.put_task(cur_task);
|
self.put_task(cur_task);
|
||||||
let sched = self.sched.take_unwrap();
|
let sched = self.sched.take_unwrap();
|
||||||
sched.yield_now(self);
|
sched.yield_now(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_yield(mut ~self, cur_task: ~Task) {
|
fn maybe_yield(mut ~self, cur_task: Box<Task>) {
|
||||||
self.put_task(cur_task);
|
self.put_task(cur_task);
|
||||||
let sched = self.sched.take_unwrap();
|
let sched = self.sched.take_unwrap();
|
||||||
sched.maybe_yield(self);
|
sched.maybe_yield(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deschedule(mut ~self, times: uint, cur_task: ~Task,
|
fn deschedule(mut ~self, times: uint, cur_task: Box<Task>,
|
||||||
f: |BlockedTask| -> Result<(), BlockedTask>) {
|
f: |BlockedTask| -> Result<(), BlockedTask>) {
|
||||||
self.put_task(cur_task);
|
self.put_task(cur_task);
|
||||||
let mut sched = self.sched.take_unwrap();
|
let mut sched = self.sched.take_unwrap();
|
||||||
|
@ -392,14 +394,14 @@ impl Runtime for GreenTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reawaken(mut ~self, to_wake: ~Task) {
|
fn reawaken(mut ~self, to_wake: Box<Task>) {
|
||||||
self.put_task(to_wake);
|
self.put_task(to_wake);
|
||||||
assert!(self.sched.is_none());
|
assert!(self.sched.is_none());
|
||||||
|
|
||||||
// Optimistically look for a local task, but if one's not available to
|
// Optimistically look for a local task, but if one's not available to
|
||||||
// inspect (in order to see if it's in the same sched pool as we are),
|
// inspect (in order to see if it's in the same sched pool as we are),
|
||||||
// then just use our remote wakeup routine and carry on!
|
// then just use our remote wakeup routine and carry on!
|
||||||
let mut running_task: ~Task = match Local::try_take() {
|
let mut running_task: Box<Task> = match Local::try_take() {
|
||||||
Some(task) => task,
|
Some(task) => task,
|
||||||
None => return self.reawaken_remotely()
|
None => return self.reawaken_remotely()
|
||||||
};
|
};
|
||||||
|
@ -443,7 +445,10 @@ impl Runtime for GreenTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_sibling(mut ~self, cur_task: ~Task, opts: TaskOpts, f: proc():Send) {
|
fn spawn_sibling(mut ~self,
|
||||||
|
cur_task: Box<Task>,
|
||||||
|
opts: TaskOpts,
|
||||||
|
f: proc():Send) {
|
||||||
self.put_task(cur_task);
|
self.put_task(cur_task);
|
||||||
|
|
||||||
// Spawns a task into the current scheduler. We allocate the new task's
|
// Spawns a task into the current scheduler. We allocate the new task's
|
||||||
|
@ -477,7 +482,7 @@ impl Runtime for GreenTask {
|
||||||
|
|
||||||
fn can_block(&self) -> bool { false }
|
fn can_block(&self) -> bool { false }
|
||||||
|
|
||||||
fn wrap(~self) -> ~Any { self as ~Any }
|
fn wrap(~self) -> Box<Any> { self as Box<Any> }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -572,7 +577,7 @@ mod tests {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
spawn_opts(TaskOpts::new(), proc() {
|
spawn_opts(TaskOpts::new(), proc() {
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
let mut task: ~Task = Local::take();
|
let mut task: Box<Task> = Local::take();
|
||||||
match task.maybe_take_runtime::<GreenTask>() {
|
match task.maybe_take_runtime::<GreenTask>() {
|
||||||
Some(ops) => {
|
Some(ops) => {
|
||||||
task.put_runtime(ops);
|
task.put_runtime(ops);
|
||||||
|
|
|
@ -61,7 +61,7 @@ use syntax::parse::token;
|
||||||
#[macro_registrar]
|
#[macro_registrar]
|
||||||
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
|
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
|
||||||
register(token::intern("hexfloat"),
|
register(token::intern("hexfloat"),
|
||||||
NormalTT(~BasicMacroExpander {
|
NormalTT(box BasicMacroExpander {
|
||||||
expander: expand_syntax_ext,
|
expander: expand_syntax_ext,
|
||||||
span: None,
|
span: None,
|
||||||
},
|
},
|
||||||
|
@ -97,7 +97,8 @@ fn hex_float_lit_err(s: &str) -> Option<(uint, ~str)> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
|
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||||
|
-> Box<base::MacResult> {
|
||||||
let (expr, ty_lit) = parse_tts(cx, tts);
|
let (expr, ty_lit) = parse_tts(cx, tts);
|
||||||
|
|
||||||
let ty = match ty_lit {
|
let ty = match ty_lit {
|
||||||
|
|
|
@ -158,7 +158,7 @@ pub static WARN: u32 = 2;
|
||||||
/// Error log level
|
/// Error log level
|
||||||
pub static ERROR: u32 = 1;
|
pub static ERROR: u32 = 1;
|
||||||
|
|
||||||
local_data_key!(local_logger: ~Logger:Send)
|
local_data_key!(local_logger: Box<Logger:Send>)
|
||||||
|
|
||||||
/// A trait used to represent an interface to a task-local logger. Each task
|
/// A trait used to represent an interface to a task-local logger. Each task
|
||||||
/// can have its own custom logger which can respond to logging messages
|
/// can have its own custom logger which can respond to logging messages
|
||||||
|
@ -229,7 +229,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: &fmt::Arguments) {
|
||||||
// frob the slot while we're doing the logging. This will destroy any logger
|
// frob the slot while we're doing the logging. This will destroy any logger
|
||||||
// set during logging.
|
// set during logging.
|
||||||
let mut logger = local_data::pop(local_logger).unwrap_or_else(|| {
|
let mut logger = local_data::pop(local_logger).unwrap_or_else(|| {
|
||||||
box DefaultLogger { handle: io::stderr() } as ~Logger:Send
|
box DefaultLogger { handle: io::stderr() } as Box<Logger:Send>
|
||||||
});
|
});
|
||||||
logger.log(&LogRecord {
|
logger.log(&LogRecord {
|
||||||
level: LogLevel(level),
|
level: LogLevel(level),
|
||||||
|
@ -249,7 +249,7 @@ pub fn log_level() -> u32 { unsafe { LOG_LEVEL } }
|
||||||
|
|
||||||
/// Replaces the task-local logger with the specified logger, returning the old
|
/// Replaces the task-local logger with the specified logger, returning the old
|
||||||
/// logger.
|
/// logger.
|
||||||
pub fn set_logger(logger: ~Logger:Send) -> Option<~Logger:Send> {
|
pub fn set_logger(logger: Box<Logger:Send>) -> Option<Box<Logger:Send>> {
|
||||||
let prev = local_data::pop(local_logger);
|
let prev = local_data::pop(local_logger);
|
||||||
local_data::set(local_logger, logger);
|
local_data::set(local_logger, logger);
|
||||||
return prev;
|
return prev;
|
||||||
|
@ -351,7 +351,7 @@ fn init() {
|
||||||
// Schedule the cleanup for this global for when the runtime exits.
|
// Schedule the cleanup for this global for when the runtime exits.
|
||||||
rt::at_exit(proc() {
|
rt::at_exit(proc() {
|
||||||
assert!(!DIRECTIVES.is_null());
|
assert!(!DIRECTIVES.is_null());
|
||||||
let _directives: ~Vec<directive::LogDirective> =
|
let _directives: Box<Vec<directive::LogDirective>> =
|
||||||
cast::transmute(DIRECTIVES);
|
cast::transmute(DIRECTIVES);
|
||||||
DIRECTIVES = 0 as *Vec<directive::LogDirective>;
|
DIRECTIVES = 0 as *Vec<directive::LogDirective>;
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
|
|
||||||
//! Blocking posix-based file I/O
|
//! Blocking posix-based file I/O
|
||||||
|
|
||||||
|
use libc::{c_int, c_void};
|
||||||
|
use libc;
|
||||||
use std::sync::arc::UnsafeArc;
|
use std::sync::arc::UnsafeArc;
|
||||||
use std::c_str::CString;
|
use std::c_str::CString;
|
||||||
use std::io::IoError;
|
use std::io::IoError;
|
||||||
use std::io;
|
use std::io;
|
||||||
use libc::{c_int, c_void};
|
|
||||||
use libc;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rt::rtio;
|
use std::rt::rtio;
|
||||||
|
|
||||||
|
@ -175,8 +175,8 @@ impl rtio::RtioPipe for FileDesc {
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
|
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
|
||||||
self.inner_write(buf)
|
self.inner_write(buf)
|
||||||
}
|
}
|
||||||
fn clone(&self) -> ~rtio::RtioPipe:Send {
|
fn clone(&self) -> Box<rtio::RtioPipe:Send> {
|
||||||
box FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe:Send
|
box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,8 +207,8 @@ impl rtio::RtioPipe for FileDesc {
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
|
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
|
||||||
self.inner_write(buf)
|
self.inner_write(buf)
|
||||||
}
|
}
|
||||||
fn clone(&self) -> ~rtio::RtioPipe:Send {
|
fn clone(&self) -> Box<rtio::RtioPipe:Send> {
|
||||||
box FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe:Send
|
box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,19 +21,19 @@
|
||||||
//! play. The only dependencies of these modules are the normal system libraries
|
//! play. The only dependencies of these modules are the normal system libraries
|
||||||
//! that you would find on the respective platform.
|
//! that you would find on the respective platform.
|
||||||
|
|
||||||
|
use libc::c_int;
|
||||||
|
use libc;
|
||||||
use std::c_str::CString;
|
use std::c_str::CString;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::IoError;
|
use std::io::IoError;
|
||||||
use std::io::net::ip::SocketAddr;
|
use std::io::net::ip::SocketAddr;
|
||||||
use std::io::process::ProcessConfig;
|
use std::io::process::ProcessConfig;
|
||||||
use std::io::signal::Signum;
|
use std::io::signal::Signum;
|
||||||
use libc::c_int;
|
|
||||||
use libc;
|
|
||||||
use std::os;
|
use std::os;
|
||||||
use std::rt::rtio;
|
use std::rt::rtio;
|
||||||
use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket,
|
use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket};
|
||||||
RtioUnixListener, RtioPipe, RtioFileStream, RtioProcess,
|
use std::rt::rtio::{RtioUnixListener, RtioPipe, RtioFileStream, RtioProcess};
|
||||||
RtioSignal, RtioTTY, CloseBehavior, RtioTimer};
|
use std::rt::rtio::{RtioSignal, RtioTTY, CloseBehavior, RtioTimer};
|
||||||
use ai = std::io::net::addrinfo;
|
use ai = std::io::net::addrinfo;
|
||||||
|
|
||||||
// Local re-exports
|
// Local re-exports
|
||||||
|
@ -166,21 +166,32 @@ impl IoFactory {
|
||||||
impl rtio::IoFactory for IoFactory {
|
impl rtio::IoFactory for IoFactory {
|
||||||
// networking
|
// networking
|
||||||
fn tcp_connect(&mut self, addr: SocketAddr,
|
fn tcp_connect(&mut self, addr: SocketAddr,
|
||||||
timeout: Option<u64>) -> IoResult<~RtioTcpStream:Send> {
|
timeout: Option<u64>) -> IoResult<Box<RtioTcpStream:Send>> {
|
||||||
net::TcpStream::connect(addr, timeout).map(|s| box s as ~RtioTcpStream:Send)
|
net::TcpStream::connect(addr, timeout).map(|s| {
|
||||||
|
box s as Box<RtioTcpStream:Send>
|
||||||
|
})
|
||||||
}
|
}
|
||||||
fn tcp_bind(&mut self, addr: SocketAddr) -> IoResult<~RtioTcpListener:Send> {
|
fn tcp_bind(&mut self, addr: SocketAddr)
|
||||||
net::TcpListener::bind(addr).map(|s| box s as ~RtioTcpListener:Send)
|
-> IoResult<Box<RtioTcpListener:Send>> {
|
||||||
|
net::TcpListener::bind(addr).map(|s| {
|
||||||
|
box s as Box<RtioTcpListener:Send>
|
||||||
|
})
|
||||||
}
|
}
|
||||||
fn udp_bind(&mut self, addr: SocketAddr) -> IoResult<~RtioUdpSocket:Send> {
|
fn udp_bind(&mut self, addr: SocketAddr)
|
||||||
net::UdpSocket::bind(addr).map(|u| box u as ~RtioUdpSocket:Send)
|
-> IoResult<Box<RtioUdpSocket:Send>> {
|
||||||
|
net::UdpSocket::bind(addr).map(|u| box u as Box<RtioUdpSocket:Send>)
|
||||||
}
|
}
|
||||||
fn unix_bind(&mut self, path: &CString) -> IoResult<~RtioUnixListener:Send> {
|
fn unix_bind(&mut self, path: &CString)
|
||||||
pipe::UnixListener::bind(path).map(|s| box s as ~RtioUnixListener:Send)
|
-> IoResult<Box<RtioUnixListener:Send>> {
|
||||||
|
pipe::UnixListener::bind(path).map(|s| {
|
||||||
|
box s as Box<RtioUnixListener:Send>
|
||||||
|
})
|
||||||
}
|
}
|
||||||
fn unix_connect(&mut self, path: &CString,
|
fn unix_connect(&mut self, path: &CString,
|
||||||
timeout: Option<u64>) -> IoResult<~RtioPipe:Send> {
|
timeout: Option<u64>) -> IoResult<Box<RtioPipe:Send>> {
|
||||||
pipe::UnixStream::connect(path, timeout).map(|s| box s as ~RtioPipe:Send)
|
pipe::UnixStream::connect(path, timeout).map(|s| {
|
||||||
|
box s as Box<RtioPipe:Send>
|
||||||
|
})
|
||||||
}
|
}
|
||||||
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
|
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
|
||||||
hint: Option<ai::Hint>) -> IoResult<~[ai::Info]> {
|
hint: Option<ai::Hint>) -> IoResult<~[ai::Info]> {
|
||||||
|
@ -188,17 +199,17 @@ impl rtio::IoFactory for IoFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// filesystem operations
|
// filesystem operations
|
||||||
fn fs_from_raw_fd(&mut self, fd: c_int,
|
fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior)
|
||||||
close: CloseBehavior) -> ~RtioFileStream:Send {
|
-> Box<RtioFileStream:Send> {
|
||||||
let close = match close {
|
let close = match close {
|
||||||
rtio::CloseSynchronously | rtio::CloseAsynchronously => true,
|
rtio::CloseSynchronously | rtio::CloseAsynchronously => true,
|
||||||
rtio::DontClose => false
|
rtio::DontClose => false
|
||||||
};
|
};
|
||||||
box file::FileDesc::new(fd, close) as ~RtioFileStream:Send
|
box file::FileDesc::new(fd, close) as Box<RtioFileStream:Send>
|
||||||
}
|
}
|
||||||
fn fs_open(&mut self, path: &CString, fm: io::FileMode, fa: io::FileAccess)
|
fn fs_open(&mut self, path: &CString, fm: io::FileMode, fa: io::FileAccess)
|
||||||
-> IoResult<~RtioFileStream:Send> {
|
-> IoResult<Box<RtioFileStream:Send>> {
|
||||||
file::open(path, fm, fa).map(|fd| box fd as ~RtioFileStream:Send)
|
file::open(path, fm, fa).map(|fd| box fd as Box<RtioFileStream:Send>)
|
||||||
}
|
}
|
||||||
fn fs_unlink(&mut self, path: &CString) -> IoResult<()> {
|
fn fs_unlink(&mut self, path: &CString) -> IoResult<()> {
|
||||||
file::unlink(path)
|
file::unlink(path)
|
||||||
|
@ -244,27 +255,29 @@ impl rtio::IoFactory for IoFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// misc
|
// misc
|
||||||
fn timer_init(&mut self) -> IoResult<~RtioTimer:Send> {
|
fn timer_init(&mut self) -> IoResult<Box<RtioTimer:Send>> {
|
||||||
timer::Timer::new().map(|t| box t as ~RtioTimer:Send)
|
timer::Timer::new().map(|t| box t as Box<RtioTimer:Send>)
|
||||||
}
|
}
|
||||||
fn spawn(&mut self, config: ProcessConfig)
|
fn spawn(&mut self, config: ProcessConfig)
|
||||||
-> IoResult<(~RtioProcess:Send, ~[Option<~RtioPipe:Send>])> {
|
-> IoResult<(Box<RtioProcess:Send>,
|
||||||
|
~[Option<Box<RtioPipe:Send>>])> {
|
||||||
process::Process::spawn(config).map(|(p, io)| {
|
process::Process::spawn(config).map(|(p, io)| {
|
||||||
(box p as ~RtioProcess:Send,
|
(box p as Box<RtioProcess:Send>,
|
||||||
io.move_iter().map(|p| p.map(|p| box p as ~RtioPipe:Send)).collect())
|
io.move_iter().map(|p| p.map(|p| {
|
||||||
|
box p as Box<RtioPipe:Send>
|
||||||
|
})).collect())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn kill(&mut self, pid: libc::pid_t, signum: int) -> IoResult<()> {
|
fn kill(&mut self, pid: libc::pid_t, signum: int) -> IoResult<()> {
|
||||||
process::Process::kill(pid, signum)
|
process::Process::kill(pid, signum)
|
||||||
}
|
}
|
||||||
fn pipe_open(&mut self, fd: c_int) -> IoResult<~RtioPipe:Send> {
|
fn pipe_open(&mut self, fd: c_int) -> IoResult<Box<RtioPipe:Send>> {
|
||||||
Ok(box file::FileDesc::new(fd, true) as ~RtioPipe:Send)
|
Ok(box file::FileDesc::new(fd, true) as Box<RtioPipe:Send>)
|
||||||
}
|
}
|
||||||
fn tty_open(&mut self, fd: c_int, _readable: bool)
|
fn tty_open(&mut self, fd: c_int, _readable: bool)
|
||||||
-> IoResult<~RtioTTY:Send>
|
-> IoResult<Box<RtioTTY:Send>> {
|
||||||
{
|
|
||||||
if unsafe { libc::isatty(fd) } != 0 {
|
if unsafe { libc::isatty(fd) } != 0 {
|
||||||
Ok(box file::FileDesc::new(fd, true) as ~RtioTTY:Send)
|
Ok(box file::FileDesc::new(fd, true) as Box<RtioTTY:Send>)
|
||||||
} else {
|
} else {
|
||||||
Err(IoError {
|
Err(IoError {
|
||||||
kind: io::MismatchedFileTypeForOperation,
|
kind: io::MismatchedFileTypeForOperation,
|
||||||
|
@ -274,7 +287,7 @@ impl rtio::IoFactory for IoFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn signal(&mut self, _signal: Signum, _channel: Sender<Signum>)
|
fn signal(&mut self, _signal: Signum, _channel: Sender<Signum>)
|
||||||
-> IoResult<~RtioSignal:Send> {
|
-> IoResult<Box<RtioSignal:Send>> {
|
||||||
Err(unimpl())
|
Err(unimpl())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -351,8 +351,10 @@ impl rtio::RtioTcpStream for TcpStream {
|
||||||
self.set_keepalive(None)
|
self.set_keepalive(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone(&self) -> ~rtio::RtioTcpStream:Send {
|
fn clone(&self) -> Box<rtio::RtioTcpStream:Send> {
|
||||||
box TcpStream { inner: self.inner.clone() } as ~rtio::RtioTcpStream:Send
|
box TcpStream {
|
||||||
|
inner: self.inner.clone(),
|
||||||
|
} as Box<rtio::RtioTcpStream:Send>
|
||||||
}
|
}
|
||||||
fn close_write(&mut self) -> IoResult<()> {
|
fn close_write(&mut self) -> IoResult<()> {
|
||||||
super::mkerr_libc(unsafe {
|
super::mkerr_libc(unsafe {
|
||||||
|
@ -418,8 +420,10 @@ impl TcpListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rtio::RtioTcpListener for TcpListener {
|
impl rtio::RtioTcpListener for TcpListener {
|
||||||
fn listen(~self) -> IoResult<~rtio::RtioTcpAcceptor:Send> {
|
fn listen(~self) -> IoResult<Box<rtio::RtioTcpAcceptor:Send>> {
|
||||||
self.native_listen(128).map(|a| box a as ~rtio::RtioTcpAcceptor:Send)
|
self.native_listen(128).map(|a| {
|
||||||
|
box a as Box<rtio::RtioTcpAcceptor:Send>
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,8 +469,8 @@ impl rtio::RtioSocket for TcpAcceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rtio::RtioTcpAcceptor for TcpAcceptor {
|
impl rtio::RtioTcpAcceptor for TcpAcceptor {
|
||||||
fn accept(&mut self) -> IoResult<~rtio::RtioTcpStream:Send> {
|
fn accept(&mut self) -> IoResult<Box<rtio::RtioTcpStream:Send>> {
|
||||||
self.native_accept().map(|s| box s as ~rtio::RtioTcpStream:Send)
|
self.native_accept().map(|s| box s as Box<rtio::RtioTcpStream:Send>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) }
|
fn accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) }
|
||||||
|
@ -637,7 +641,9 @@ impl rtio::RtioUdpSocket for UdpSocket {
|
||||||
self.set_broadcast(false)
|
self.set_broadcast(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone(&self) -> ~rtio::RtioUdpSocket:Send {
|
fn clone(&self) -> Box<rtio::RtioUdpSocket:Send> {
|
||||||
box UdpSocket { inner: self.inner.clone() } as ~rtio::RtioUdpSocket:Send
|
box UdpSocket {
|
||||||
|
inner: self.inner.clone(),
|
||||||
|
} as Box<rtio::RtioUdpSocket:Send>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,8 +144,10 @@ impl rtio::RtioPipe for UnixStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone(&self) -> ~rtio::RtioPipe:Send {
|
fn clone(&self) -> Box<rtio::RtioPipe:Send> {
|
||||||
box UnixStream { inner: self.inner.clone() } as ~rtio::RtioPipe:Send
|
box UnixStream {
|
||||||
|
inner: self.inner.clone(),
|
||||||
|
} as Box<rtio::RtioPipe:Send>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +178,10 @@ impl UnixListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rtio::RtioUnixListener for UnixListener {
|
impl rtio::RtioUnixListener for UnixListener {
|
||||||
fn listen(~self) -> IoResult<~rtio::RtioUnixAcceptor:Send> {
|
fn listen(~self) -> IoResult<Box<rtio::RtioUnixAcceptor:Send>> {
|
||||||
self.native_listen(128).map(|a| box a as ~rtio::RtioUnixAcceptor:Send)
|
self.native_listen(128).map(|a| {
|
||||||
|
box a as Box<rtio::RtioUnixAcceptor:Send>
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,8 +213,8 @@ impl UnixAcceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rtio::RtioUnixAcceptor for UnixAcceptor {
|
impl rtio::RtioUnixAcceptor for UnixAcceptor {
|
||||||
fn accept(&mut self) -> IoResult<~rtio::RtioPipe:Send> {
|
fn accept(&mut self) -> IoResult<Box<rtio::RtioPipe:Send>> {
|
||||||
self.native_accept().map(|s| box s as ~rtio::RtioPipe:Send)
|
self.native_accept().map(|s| box s as Box<rtio::RtioPipe:Send>)
|
||||||
}
|
}
|
||||||
fn set_timeout(&mut self, timeout: Option<u64>) {
|
fn set_timeout(&mut self, timeout: Option<u64>) {
|
||||||
self.deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
|
self.deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
|
||||||
|
|
|
@ -353,12 +353,12 @@ impl rtio::RtioPipe for UnixStream {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone(&self) -> ~rtio::RtioPipe:Send {
|
fn clone(&self) -> Box<rtio::RtioPipe:Send> {
|
||||||
box UnixStream {
|
box UnixStream {
|
||||||
inner: self.inner.clone(),
|
inner: self.inner.clone(),
|
||||||
read: None,
|
read: None,
|
||||||
write: None,
|
write: None,
|
||||||
} as ~rtio::RtioPipe:Send
|
} as Box<rtio::RtioPipe:Send>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,8 +402,10 @@ impl Drop for UnixListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rtio::RtioUnixListener for UnixListener {
|
impl rtio::RtioUnixListener for UnixListener {
|
||||||
fn listen(~self) -> IoResult<~rtio::RtioUnixAcceptor:Send> {
|
fn listen(~self) -> IoResult<Box<rtio::RtioUnixAcceptor:Send>> {
|
||||||
self.native_listen().map(|a| box a as ~rtio::RtioUnixAcceptor:Send)
|
self.native_listen().map(|a| {
|
||||||
|
box a as Box<rtio::RtioUnixAcceptor:Send>
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,8 +528,8 @@ impl UnixAcceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rtio::RtioUnixAcceptor for UnixAcceptor {
|
impl rtio::RtioUnixAcceptor for UnixAcceptor {
|
||||||
fn accept(&mut self) -> IoResult<~rtio::RtioPipe:Send> {
|
fn accept(&mut self) -> IoResult<Box<rtio::RtioPipe:Send>> {
|
||||||
self.native_accept().map(|s| box s as ~rtio::RtioPipe:Send)
|
self.native_accept().map(|s| box s as Box<rtio::RtioPipe:Send>)
|
||||||
}
|
}
|
||||||
fn set_timeout(&mut self, timeout: Option<u64>) {
|
fn set_timeout(&mut self, timeout: Option<u64>) {
|
||||||
self.deadline = timeout.map(|i| i + ::io::timer::now()).unwrap_or(0);
|
self.deadline = timeout.map(|i| i + ::io::timer::now()).unwrap_or(0);
|
||||||
|
|
|
@ -86,7 +86,7 @@ fn shutdown() {
|
||||||
// Clean up after ther helper thread
|
// Clean up after ther helper thread
|
||||||
unsafe {
|
unsafe {
|
||||||
imp::close(HELPER_SIGNAL);
|
imp::close(HELPER_SIGNAL);
|
||||||
let _chan: ~Sender<Req> = cast::transmute(HELPER_CHAN);
|
let _chan: Box<Sender<Req>> = cast::transmute(HELPER_CHAN);
|
||||||
HELPER_CHAN = 0 as *mut Sender<Req>;
|
HELPER_CHAN = 0 as *mut Sender<Req>;
|
||||||
HELPER_SIGNAL = 0 as imp::signal;
|
HELPER_SIGNAL = 0 as imp::signal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ use io::timer_helper;
|
||||||
|
|
||||||
pub struct Timer {
|
pub struct Timer {
|
||||||
id: uint,
|
id: uint,
|
||||||
inner: Option<~Inner>,
|
inner: Option<Box<Inner>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Inner {
|
struct Inner {
|
||||||
|
@ -74,11 +74,11 @@ struct Inner {
|
||||||
#[allow(visible_private_types)]
|
#[allow(visible_private_types)]
|
||||||
pub enum Req {
|
pub enum Req {
|
||||||
// Add a new timer to the helper thread.
|
// Add a new timer to the helper thread.
|
||||||
NewTimer(~Inner),
|
NewTimer(Box<Inner>),
|
||||||
|
|
||||||
// Remove a timer based on its id and then send it back on the channel
|
// Remove a timer based on its id and then send it back on the channel
|
||||||
// provided
|
// provided
|
||||||
RemoveTimer(uint, Sender<~Inner>),
|
RemoveTimer(uint, Sender<Box<Inner>>),
|
||||||
|
|
||||||
// Shut down the loop and then ACK this channel once it's shut down
|
// Shut down the loop and then ACK this channel once it's shut down
|
||||||
Shutdown,
|
Shutdown,
|
||||||
|
@ -102,11 +102,11 @@ fn helper(input: libc::c_int, messages: Receiver<Req>) {
|
||||||
// active timers are those which are able to be selected upon (and it's a
|
// active timers are those which are able to be selected upon (and it's a
|
||||||
// sorted list, and dead timers are those which have expired, but ownership
|
// sorted list, and dead timers are those which have expired, but ownership
|
||||||
// hasn't yet been transferred back to the timer itself.
|
// hasn't yet been transferred back to the timer itself.
|
||||||
let mut active: Vec<~Inner> = vec![];
|
let mut active: Vec<Box<Inner>> = vec![];
|
||||||
let mut dead = vec![];
|
let mut dead = vec![];
|
||||||
|
|
||||||
// inserts a timer into an array of timers (sorted by firing time)
|
// inserts a timer into an array of timers (sorted by firing time)
|
||||||
fn insert(t: ~Inner, active: &mut Vec<~Inner>) {
|
fn insert(t: Box<Inner>, active: &mut Vec<Box<Inner>>) {
|
||||||
match active.iter().position(|tm| tm.target > t.target) {
|
match active.iter().position(|tm| tm.target > t.target) {
|
||||||
Some(pos) => { active.insert(pos, t); }
|
Some(pos) => { active.insert(pos, t); }
|
||||||
None => { active.push(t); }
|
None => { active.push(t); }
|
||||||
|
@ -114,7 +114,8 @@ fn helper(input: libc::c_int, messages: Receiver<Req>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// signals the first requests in the queue, possible re-enqueueing it.
|
// signals the first requests in the queue, possible re-enqueueing it.
|
||||||
fn signal(active: &mut Vec<~Inner>, dead: &mut Vec<(uint, ~Inner)>) {
|
fn signal(active: &mut Vec<Box<Inner>>,
|
||||||
|
dead: &mut Vec<(uint, Box<Inner>)>) {
|
||||||
let mut timer = match active.shift() {
|
let mut timer = match active.shift() {
|
||||||
Some(timer) => timer, None => return
|
Some(timer) => timer, None => return
|
||||||
};
|
};
|
||||||
|
@ -229,7 +230,7 @@ impl Timer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner(&mut self) -> ~Inner {
|
fn inner(&mut self) -> Box<Inner> {
|
||||||
match self.inner.take() {
|
match self.inner.take() {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -31,7 +31,7 @@ use io;
|
||||||
use task;
|
use task;
|
||||||
|
|
||||||
/// Creates a new Task which is ready to execute as a 1:1 task.
|
/// Creates a new Task which is ready to execute as a 1:1 task.
|
||||||
pub fn new(stack_bounds: (uint, uint)) -> ~Task {
|
pub fn new(stack_bounds: (uint, uint)) -> Box<Task> {
|
||||||
let mut task = box Task::new();
|
let mut task = box Task::new();
|
||||||
let mut ops = ops();
|
let mut ops = ops();
|
||||||
ops.stack_bounds = stack_bounds;
|
ops.stack_bounds = stack_bounds;
|
||||||
|
@ -39,7 +39,7 @@ pub fn new(stack_bounds: (uint, uint)) -> ~Task {
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ops() -> ~Ops {
|
fn ops() -> Box<Ops> {
|
||||||
box Ops {
|
box Ops {
|
||||||
lock: unsafe { NativeMutex::new() },
|
lock: unsafe { NativeMutex::new() },
|
||||||
awoken: false,
|
awoken: false,
|
||||||
|
@ -119,22 +119,22 @@ struct Ops {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rt::Runtime for Ops {
|
impl rt::Runtime for Ops {
|
||||||
fn yield_now(~self, mut cur_task: ~Task) {
|
fn yield_now(~self, mut cur_task: Box<Task>) {
|
||||||
// put the task back in TLS and then invoke the OS thread yield
|
// put the task back in TLS and then invoke the OS thread yield
|
||||||
cur_task.put_runtime(self);
|
cur_task.put_runtime(self);
|
||||||
Local::put(cur_task);
|
Local::put(cur_task);
|
||||||
Thread::yield_now();
|
Thread::yield_now();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_yield(~self, mut cur_task: ~Task) {
|
fn maybe_yield(~self, mut cur_task: Box<Task>) {
|
||||||
// just put the task back in TLS, on OS threads we never need to
|
// just put the task back in TLS, on OS threads we never need to
|
||||||
// opportunistically yield b/c the OS will do that for us (preemption)
|
// opportunistically yield b/c the OS will do that for us (preemption)
|
||||||
cur_task.put_runtime(self);
|
cur_task.put_runtime(self);
|
||||||
Local::put(cur_task);
|
Local::put(cur_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap(~self) -> ~Any {
|
fn wrap(~self) -> Box<Any> {
|
||||||
self as ~Any
|
self as Box<Any>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stack_bounds(&self) -> (uint, uint) { self.stack_bounds }
|
fn stack_bounds(&self) -> (uint, uint) { self.stack_bounds }
|
||||||
|
@ -159,8 +159,8 @@ impl rt::Runtime for Ops {
|
||||||
// from the wakeup thread back to this thread about the task pointer, and
|
// from the wakeup thread back to this thread about the task pointer, and
|
||||||
// there's really no need to. In order to get around this, we cast the task
|
// there's really no need to. In order to get around this, we cast the task
|
||||||
// to a `uint` which is then used at the end of this function to cast back
|
// to a `uint` which is then used at the end of this function to cast back
|
||||||
// to a `~Task` object. Naturally, this looks like it violates ownership
|
// to a `Box<Task>` object. Naturally, this looks like it violates
|
||||||
// semantics in that there may be two `~Task` objects.
|
// ownership semantics in that there may be two `Box<Task>` objects.
|
||||||
//
|
//
|
||||||
// The fun part is that the wakeup half of this implementation knows to
|
// The fun part is that the wakeup half of this implementation knows to
|
||||||
// "forget" the task on the other end. This means that the awakening half of
|
// "forget" the task on the other end. This means that the awakening half of
|
||||||
|
@ -180,7 +180,7 @@ impl rt::Runtime for Ops {
|
||||||
// `awoken` field which indicates whether we were actually woken up via some
|
// `awoken` field which indicates whether we were actually woken up via some
|
||||||
// invocation of `reawaken`. This flag is only ever accessed inside the
|
// invocation of `reawaken`. This flag is only ever accessed inside the
|
||||||
// lock, so there's no need to make it atomic.
|
// lock, so there's no need to make it atomic.
|
||||||
fn deschedule(mut ~self, times: uint, mut cur_task: ~Task,
|
fn deschedule(mut ~self, times: uint, mut cur_task: Box<Task>,
|
||||||
f: |BlockedTask| -> Result<(), BlockedTask>) {
|
f: |BlockedTask| -> Result<(), BlockedTask>) {
|
||||||
let me = &mut *self as *mut Ops;
|
let me = &mut *self as *mut Ops;
|
||||||
cur_task.put_runtime(self);
|
cur_task.put_runtime(self);
|
||||||
|
@ -238,7 +238,7 @@ impl rt::Runtime for Ops {
|
||||||
|
|
||||||
// See the comments on `deschedule` for why the task is forgotten here, and
|
// See the comments on `deschedule` for why the task is forgotten here, and
|
||||||
// why it's valid to do so.
|
// why it's valid to do so.
|
||||||
fn reawaken(mut ~self, mut to_wake: ~Task) {
|
fn reawaken(mut ~self, mut to_wake: Box<Task>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let me = &mut *self as *mut Ops;
|
let me = &mut *self as *mut Ops;
|
||||||
to_wake.put_runtime(self);
|
to_wake.put_runtime(self);
|
||||||
|
@ -249,7 +249,10 @@ impl rt::Runtime for Ops {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_sibling(~self, mut cur_task: ~Task, opts: TaskOpts, f: proc():Send) {
|
fn spawn_sibling(~self,
|
||||||
|
mut cur_task: Box<Task>,
|
||||||
|
opts: TaskOpts,
|
||||||
|
f: proc():Send) {
|
||||||
cur_task.put_runtime(self);
|
cur_task.put_runtime(self);
|
||||||
Local::put(cur_task);
|
Local::put(cur_task);
|
||||||
|
|
||||||
|
@ -342,7 +345,7 @@ mod tests {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
let mut task: ~Task = Local::take();
|
let mut task: Box<Task> = Local::take();
|
||||||
match task.maybe_take_runtime::<Ops>() {
|
match task.maybe_take_runtime::<Ops>() {
|
||||||
Some(ops) => {
|
Some(ops) => {
|
||||||
task.put_runtime(ops);
|
task.put_runtime(ops);
|
||||||
|
|
|
@ -57,7 +57,7 @@ if rng.gen() { // bool
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let tuple_ptr = rand::random::<~(f64, char)>();
|
let tuple_ptr = rand::random::<Box<(f64, char)>>();
|
||||||
println!("{:?}", tuple_ptr)
|
println!("{:?}", tuple_ptr)
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
|
@ -569,7 +569,7 @@ type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
|
||||||
/// The task-local RNG.
|
/// The task-local RNG.
|
||||||
pub struct TaskRng {
|
pub struct TaskRng {
|
||||||
// This points into TLS (specifically, it points to the endpoint
|
// This points into TLS (specifically, it points to the endpoint
|
||||||
// of a ~ stored in TLS, to make it robust against TLS moving
|
// of a Box stored in TLS, to make it robust against TLS moving
|
||||||
// things internally) and so this struct cannot be legally
|
// things internally) and so this struct cannot be legally
|
||||||
// transferred between tasks *and* it's unsafe to deallocate the
|
// transferred between tasks *and* it's unsafe to deallocate the
|
||||||
// RNG other than when a task is finished.
|
// RNG other than when a task is finished.
|
||||||
|
@ -582,7 +582,7 @@ pub struct TaskRng {
|
||||||
}
|
}
|
||||||
|
|
||||||
// used to make space in TLS for a random number generator
|
// used to make space in TLS for a random number generator
|
||||||
local_data_key!(TASK_RNG_KEY: ~TaskRngInner)
|
local_data_key!(TASK_RNG_KEY: Box<TaskRngInner>)
|
||||||
|
|
||||||
/// Retrieve the lazily-initialized task-local random number
|
/// Retrieve the lazily-initialized task-local random number
|
||||||
/// generator, seeded by the system. Intended to be used in method
|
/// generator, seeded by the system. Intended to be used in method
|
||||||
|
@ -833,7 +833,9 @@ mod test {
|
||||||
let _f : f32 = random();
|
let _f : f32 = random();
|
||||||
let _o : Option<Option<i8>> = random();
|
let _o : Option<Option<i8>> = random();
|
||||||
let _many : ((),
|
let _many : ((),
|
||||||
(~uint, @int, ~Option<~(@u32, ~(@bool,))>),
|
(Box<uint>,
|
||||||
|
@int,
|
||||||
|
Box<Option<Box<(@u32, Box<(@bool,)>)>>>),
|
||||||
(u8, i8, u16, i16, u32, i32, u64, i64),
|
(u8, i8, u16, i16, u32, i32, u64, i64),
|
||||||
(f32, (f64, (f64,)))) = random();
|
(f32, (f64, (f64,)))) = random();
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,9 +214,9 @@ impl<T:Rand> Rand for Option<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Rand> Rand for ~T {
|
impl<T: Rand> Rand for Box<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> ~T { box rng.gen() }
|
fn rand<R: Rng>(rng: &mut R) -> Box<T> { box rng.gen() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Rand + 'static> Rand for @T {
|
impl<T: Rand + 'static> Rand for @T {
|
||||||
|
|
|
@ -59,12 +59,12 @@ pub enum Ast {
|
||||||
Begin(Flags),
|
Begin(Flags),
|
||||||
End(Flags),
|
End(Flags),
|
||||||
WordBoundary(Flags),
|
WordBoundary(Flags),
|
||||||
Capture(uint, Option<~str>, ~Ast),
|
Capture(uint, Option<~str>, Box<Ast>),
|
||||||
// Represent concatenation as a flat vector to avoid blowing the
|
// Represent concatenation as a flat vector to avoid blowing the
|
||||||
// stack in the compiler.
|
// stack in the compiler.
|
||||||
Cat(Vec<Ast>),
|
Cat(Vec<Ast>),
|
||||||
Alt(~Ast, ~Ast),
|
Alt(Box<Ast>, Box<Ast>),
|
||||||
Rep(~Ast, Repeater, Greed),
|
Rep(Box<Ast>, Repeater, Greed),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Show, Eq, Clone)]
|
#[deriving(Show, Eq, Clone)]
|
||||||
|
@ -245,7 +245,7 @@ impl<'a> Parser<'a> {
|
||||||
// alternate and make it a capture.
|
// alternate and make it a capture.
|
||||||
if cap.is_some() {
|
if cap.is_some() {
|
||||||
let ast = try!(self.pop_ast());
|
let ast = try!(self.pop_ast());
|
||||||
self.push(Capture(cap.unwrap(), cap_name, ~ast));
|
self.push(Capture(cap.unwrap(), cap_name, box ast));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'|' => {
|
'|' => {
|
||||||
|
@ -331,7 +331,7 @@ impl<'a> Parser<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let greed = try!(self.get_next_greedy());
|
let greed = try!(self.get_next_greedy());
|
||||||
self.push(Rep(~ast, rep, greed));
|
self.push(Rep(box ast, rep, greed));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,13 +411,13 @@ impl<'a> Parser<'a> {
|
||||||
let flags = negated | (self.flags & FLAG_NOCASE);
|
let flags = negated | (self.flags & FLAG_NOCASE);
|
||||||
let mut ast = Class(combine_ranges(ranges), flags);
|
let mut ast = Class(combine_ranges(ranges), flags);
|
||||||
for alt in alts.move_iter() {
|
for alt in alts.move_iter() {
|
||||||
ast = Alt(~alt, ~ast)
|
ast = Alt(box alt, box ast)
|
||||||
}
|
}
|
||||||
self.push(ast);
|
self.push(ast);
|
||||||
} else if alts.len() > 0 {
|
} else if alts.len() > 0 {
|
||||||
let mut ast = alts.pop().unwrap();
|
let mut ast = alts.pop().unwrap();
|
||||||
for alt in alts.move_iter() {
|
for alt in alts.move_iter() {
|
||||||
ast = Alt(~alt, ~ast)
|
ast = Alt(box alt, box ast)
|
||||||
}
|
}
|
||||||
self.push(ast);
|
self.push(ast);
|
||||||
}
|
}
|
||||||
|
@ -548,7 +548,7 @@ impl<'a> Parser<'a> {
|
||||||
for _ in iter::range(0, min) {
|
for _ in iter::range(0, min) {
|
||||||
self.push(ast.clone())
|
self.push(ast.clone())
|
||||||
}
|
}
|
||||||
self.push(Rep(~ast, ZeroMore, greed));
|
self.push(Rep(box ast, ZeroMore, greed));
|
||||||
} else {
|
} else {
|
||||||
// Require N copies of what's on the stack and then repeat it
|
// Require N copies of what's on the stack and then repeat it
|
||||||
// up to M times optionally.
|
// up to M times optionally.
|
||||||
|
@ -558,7 +558,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
if max.is_some() {
|
if max.is_some() {
|
||||||
for _ in iter::range(min, max.unwrap()) {
|
for _ in iter::range(min, max.unwrap()) {
|
||||||
self.push(Rep(~ast.clone(), ZeroOne, greed))
|
self.push(Rep(box ast.clone(), ZeroOne, greed))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// It's possible that we popped something off the stack but
|
// It's possible that we popped something off the stack but
|
||||||
|
@ -842,7 +842,7 @@ impl<'a> Parser<'a> {
|
||||||
// thrown away). But be careful with overflow---we can't count on the
|
// thrown away). But be careful with overflow---we can't count on the
|
||||||
// open paren to be there.
|
// open paren to be there.
|
||||||
if from > 0 { from = from - 1}
|
if from > 0 { from = from - 1}
|
||||||
let ast = try!(self.build_from(from, |l,r| Alt(~l, ~r)));
|
let ast = try!(self.build_from(from, |l,r| Alt(box l, box r)));
|
||||||
self.push(ast);
|
self.push(ast);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ use regex::native::{
|
||||||
#[macro_registrar]
|
#[macro_registrar]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn macro_registrar(register: |ast::Name, SyntaxExtension|) {
|
pub fn macro_registrar(register: |ast::Name, SyntaxExtension|) {
|
||||||
let expander = ~BasicMacroExpander { expander: native, span: None };
|
let expander = box BasicMacroExpander { expander: native, span: None };
|
||||||
register(token::intern("regex"), NormalTT(expander, None))
|
register(token::intern("regex"), NormalTT(expander, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ pub fn macro_registrar(register: |ast::Name, SyntaxExtension|) {
|
||||||
/// first before trying to understand the code generator. The implementation
|
/// first before trying to understand the code generator. The implementation
|
||||||
/// strategy is identical and vm.rs has comments and will be easier to follow.
|
/// strategy is identical and vm.rs has comments and will be easier to follow.
|
||||||
fn native(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree])
|
fn native(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree])
|
||||||
-> ~MacResult {
|
-> Box<MacResult> {
|
||||||
let regex = match parse(cx, tts) {
|
let regex = match parse(cx, tts) {
|
||||||
Some(r) => r,
|
Some(r) => r,
|
||||||
// error is logged in 'parse' with cx.span_err
|
// error is logged in 'parse' with cx.span_err
|
||||||
|
|
|
@ -677,11 +677,11 @@ pub fn pretty_print_input(sess: Session,
|
||||||
let mut rdr = MemReader::new(src);
|
let mut rdr = MemReader::new(src);
|
||||||
|
|
||||||
let out = match ofile {
|
let out = match ofile {
|
||||||
None => box io::stdout() as ~Writer,
|
None => box io::stdout() as Box<Writer>,
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
let r = io::File::create(&p);
|
let r = io::File::create(&p);
|
||||||
match r {
|
match r {
|
||||||
Ok(w) => box w as ~Writer,
|
Ok(w) => box w as Box<Writer>,
|
||||||
Err(e) => fail!("print-print failed to open {} due to {}",
|
Err(e) => fail!("print-print failed to open {} due to {}",
|
||||||
p.display(), e),
|
p.display(), e),
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,7 +229,12 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
|
||||||
enc_substs(w, cx, substs);
|
enc_substs(w, cx, substs);
|
||||||
mywrite!(w, "]");
|
mywrite!(w, "]");
|
||||||
}
|
}
|
||||||
ty::ty_trait(~ty::TyTrait { def_id, ref substs, store, bounds }) => {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
|
def_id,
|
||||||
|
ref substs,
|
||||||
|
store,
|
||||||
|
bounds
|
||||||
|
}) => {
|
||||||
mywrite!(w, "x[{}|", (cx.ds)(def_id));
|
mywrite!(w, "x[{}|", (cx.ds)(def_id));
|
||||||
enc_substs(w, cx, substs);
|
enc_substs(w, cx, substs);
|
||||||
enc_trait_store(w, cx, store);
|
enc_trait_store(w, cx, store);
|
||||||
|
|
|
@ -68,13 +68,13 @@ niceties. This means that if you have a type like:
|
||||||
struct S { f: uint }
|
struct S { f: uint }
|
||||||
```
|
```
|
||||||
|
|
||||||
and a variable `a: ~S`, then the rust expression `a.f` would correspond
|
and a variable `a: Box<S>`, then the rust expression `a.f` would correspond
|
||||||
to an `LV` of `(*a).f`.
|
to an `LV` of `(*a).f`.
|
||||||
|
|
||||||
Here is the formal grammar for the types we'll consider:
|
Here is the formal grammar for the types we'll consider:
|
||||||
|
|
||||||
```notrust
|
```notrust
|
||||||
TY = () | S<'LT...> | ~TY | & 'LT MQ TY | @ MQ TY
|
TY = () | S<'LT...> | Box<TY> | & 'LT MQ TY | @ MQ TY
|
||||||
MQ = mut | imm | const
|
MQ = mut | imm | const
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ Now, imagine we had a program like this:
|
||||||
struct Foo { f: uint, g: uint }
|
struct Foo { f: uint, g: uint }
|
||||||
...
|
...
|
||||||
'a: {
|
'a: {
|
||||||
let mut x: ~Foo = ...;
|
let mut x: Box<Foo> = ...;
|
||||||
let y = &mut (*x).f;
|
let y = &mut (*x).f;
|
||||||
x = ...;
|
x = ...;
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ MUTABILITY(LV.f, MQ) // M-Field
|
||||||
MUTABILITY(LV, MQ)
|
MUTABILITY(LV, MQ)
|
||||||
|
|
||||||
MUTABILITY(*LV, MQ) // M-Deref-Unique
|
MUTABILITY(*LV, MQ) // M-Deref-Unique
|
||||||
TYPE(LV) = ~Ty
|
TYPE(LV) = Box<Ty>
|
||||||
MUTABILITY(LV, MQ)
|
MUTABILITY(LV, MQ)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -420,7 +420,7 @@ The scope of a unique referent is the scope of the pointer, since
|
||||||
the pointer itself `LV` goes out of scope:
|
the pointer itself `LV` goes out of scope:
|
||||||
|
|
||||||
```notrust
|
```notrust
|
||||||
SCOPE(*LV) = SCOPE(LV) if LV has type ~T
|
SCOPE(*LV) = SCOPE(LV) if LV has type Box<T>
|
||||||
```
|
```
|
||||||
|
|
||||||
The scope of a managed referent is also the scope of the pointer. This
|
The scope of a managed referent is also the scope of the pointer. This
|
||||||
|
@ -459,7 +459,7 @@ LIFETIME(LV.f, LT, MQ) // L-Field
|
||||||
LIFETIME(LV, LT, MQ)
|
LIFETIME(LV, LT, MQ)
|
||||||
|
|
||||||
LIFETIME(*LV, LT, MQ) // L-Deref-Send
|
LIFETIME(*LV, LT, MQ) // L-Deref-Send
|
||||||
TYPE(LV) = ~Ty
|
TYPE(LV) = Box<Ty>
|
||||||
LIFETIME(LV, LT, MQ)
|
LIFETIME(LV, LT, MQ)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -595,7 +595,7 @@ on `LV`:
|
||||||
|
|
||||||
```notrust
|
```notrust
|
||||||
RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer
|
RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer
|
||||||
TYPE(LV) = ~Ty
|
TYPE(LV) = Box<Ty>
|
||||||
RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS
|
RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -967,8 +967,8 @@ moves/uninitializations of the variable that is being used.
|
||||||
Let's look at a simple example:
|
Let's look at a simple example:
|
||||||
|
|
||||||
```
|
```
|
||||||
fn foo(a: ~int) {
|
fn foo(a: Box<int>) {
|
||||||
let b: ~int; // Gen bit 0.
|
let b: Box<int>; // Gen bit 0.
|
||||||
|
|
||||||
if cond { // Bits: 0
|
if cond { // Bits: 0
|
||||||
use(&*a);
|
use(&*a);
|
||||||
|
|
|
@ -533,7 +533,10 @@ impl<'a> BorrowckCtxt<'a> {
|
||||||
fn move_suggestion(tcx: &ty::ctxt, ty: ty::t, default_msg: &'static str)
|
fn move_suggestion(tcx: &ty::ctxt, ty: ty::t, default_msg: &'static str)
|
||||||
-> &'static str {
|
-> &'static str {
|
||||||
match ty::get(ty).sty {
|
match ty::get(ty).sty {
|
||||||
ty::ty_closure(~ty::ClosureTy { store: ty::RegionTraitStore(..), .. }) =>
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
|
store: ty::RegionTraitStore(..),
|
||||||
|
..
|
||||||
|
}) =>
|
||||||
"a non-copyable stack closure (capture it in a new closure, \
|
"a non-copyable stack closure (capture it in a new closure, \
|
||||||
e.g. `|x| f(x)`, to override)",
|
e.g. `|x| f(x)`, to override)",
|
||||||
_ if ty::type_moves_by_default(tcx, ty) =>
|
_ if ty::type_moves_by_default(tcx, ty) =>
|
||||||
|
|
|
@ -321,7 +321,7 @@ impl<'a, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, O> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pretty_print_to(&self, wr: ~io::Writer,
|
fn pretty_print_to(&self, wr: Box<io::Writer>,
|
||||||
blk: &ast::Block) -> io::IoResult<()> {
|
blk: &ast::Block) -> io::IoResult<()> {
|
||||||
let mut ps = pprust::rust_printer_annotated(wr, self);
|
let mut ps = pprust::rust_printer_annotated(wr, self);
|
||||||
try!(ps.cbox(pprust::indent_unit));
|
try!(ps.cbox(pprust::indent_unit));
|
||||||
|
|
|
@ -51,7 +51,7 @@ fn should_explore(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
|
||||||
struct MarkSymbolVisitor<'a> {
|
struct MarkSymbolVisitor<'a> {
|
||||||
worklist: Vec<ast::NodeId>,
|
worklist: Vec<ast::NodeId>,
|
||||||
tcx: &'a ty::ctxt,
|
tcx: &'a ty::ctxt,
|
||||||
live_symbols: ~HashSet<ast::NodeId>,
|
live_symbols: Box<HashSet<ast::NodeId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MarkSymbolVisitor<'a> {
|
impl<'a> MarkSymbolVisitor<'a> {
|
||||||
|
@ -285,7 +285,7 @@ fn find_live(tcx: &ty::ctxt,
|
||||||
exported_items: &privacy::ExportedItems,
|
exported_items: &privacy::ExportedItems,
|
||||||
reachable_symbols: &NodeSet,
|
reachable_symbols: &NodeSet,
|
||||||
krate: &ast::Crate)
|
krate: &ast::Crate)
|
||||||
-> ~HashSet<ast::NodeId> {
|
-> Box<HashSet<ast::NodeId>> {
|
||||||
let worklist = create_and_seed_worklist(tcx, exported_items,
|
let worklist = create_and_seed_worklist(tcx, exported_items,
|
||||||
reachable_symbols, krate);
|
reachable_symbols, krate);
|
||||||
let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist);
|
let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist);
|
||||||
|
@ -312,7 +312,7 @@ fn get_struct_ctor_id(item: &ast::Item) -> Option<ast::NodeId> {
|
||||||
|
|
||||||
struct DeadVisitor<'a> {
|
struct DeadVisitor<'a> {
|
||||||
tcx: &'a ty::ctxt,
|
tcx: &'a ty::ctxt,
|
||||||
live_symbols: ~HashSet<ast::NodeId>,
|
live_symbols: Box<HashSet<ast::NodeId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DeadVisitor<'a> {
|
impl<'a> DeadVisitor<'a> {
|
||||||
|
|
|
@ -198,11 +198,11 @@ fn with_appropriate_checker(cx: &Context,
|
||||||
|
|
||||||
let fty = ty::node_id_to_type(cx.tcx, id);
|
let fty = ty::node_id_to_type(cx.tcx, id);
|
||||||
match ty::get(fty).sty {
|
match ty::get(fty).sty {
|
||||||
ty::ty_closure(~ty::ClosureTy {
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
store: ty::UniqTraitStore, bounds, ..
|
store: ty::UniqTraitStore, bounds, ..
|
||||||
}) => b(|cx, fv| check_for_uniq(cx, fv, bounds)),
|
}) => b(|cx, fv| check_for_uniq(cx, fv, bounds)),
|
||||||
|
|
||||||
ty::ty_closure(~ty::ClosureTy {
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
store: ty::RegionTraitStore(region, _), bounds, ..
|
store: ty::RegionTraitStore(region, _), bounds, ..
|
||||||
}) => b(|cx, fv| check_for_block(cx, fv, bounds, region)),
|
}) => b(|cx, fv| check_for_block(cx, fv, bounds, region)),
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
|
||||||
fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span: Span) {
|
fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span: Span) {
|
||||||
check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
|
check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
|
||||||
match ty::get(target_ty).sty {
|
match ty::get(target_ty).sty {
|
||||||
ty::ty_trait(~ty::TyTrait { bounds, .. }) => {
|
ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
|
||||||
check_trait_cast_bounds(cx, span, source_ty, bounds);
|
check_trait_cast_bounds(cx, span, source_ty, bounds);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -240,14 +240,14 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
|
||||||
("owned_heap_memory",
|
("owned_heap_memory",
|
||||||
LintSpec {
|
LintSpec {
|
||||||
lint: OwnedHeapMemory,
|
lint: OwnedHeapMemory,
|
||||||
desc: "use of owned (~ type) heap memory",
|
desc: "use of owned (Box type) heap memory",
|
||||||
default: allow
|
default: allow
|
||||||
}),
|
}),
|
||||||
|
|
||||||
("heap_memory",
|
("heap_memory",
|
||||||
LintSpec {
|
LintSpec {
|
||||||
lint: HeapMemory,
|
lint: HeapMemory,
|
||||||
desc: "use of any (~ type or @ type) heap memory",
|
desc: "use of any (Box type or @ type) heap memory",
|
||||||
default: allow
|
default: allow
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -943,8 +943,13 @@ fn check_heap_type(cx: &Context, span: Span, ty: ty::t) {
|
||||||
n_box += 1;
|
n_box += 1;
|
||||||
}
|
}
|
||||||
ty::ty_uniq(_) |
|
ty::ty_uniq(_) |
|
||||||
ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) |
|
ty::ty_trait(box ty::TyTrait {
|
||||||
ty::ty_closure(~ty::ClosureTy { store: ty::UniqTraitStore, .. }) => {
|
store: ty::UniqTraitStore, ..
|
||||||
|
}) |
|
||||||
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
|
store: ty::UniqTraitStore,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
n_uniq += 1;
|
n_uniq += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,7 +960,7 @@ fn check_heap_type(cx: &Context, span: Span, ty: ty::t) {
|
||||||
|
|
||||||
if n_uniq > 0 && lint != ManagedHeapMemory {
|
if n_uniq > 0 && lint != ManagedHeapMemory {
|
||||||
let s = ty_to_str(cx.tcx, ty);
|
let s = ty_to_str(cx.tcx, ty);
|
||||||
let m = format!("type uses owned (~ type) pointers: {}", s);
|
let m = format!("type uses owned (Box type) pointers: {}", s);
|
||||||
cx.span_lint(lint, span, m);
|
cx.span_lint(lint, span, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,8 +173,8 @@ pub enum deref_kind {
|
||||||
pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
|
pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
|
||||||
match ty::get(t).sty {
|
match ty::get(t).sty {
|
||||||
ty::ty_uniq(_) |
|
ty::ty_uniq(_) |
|
||||||
ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) |
|
ty::ty_trait(box ty::TyTrait { store: ty::UniqTraitStore, .. }) |
|
||||||
ty::ty_closure(~ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
|
ty::ty_closure(box ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
|
||||||
Some(deref_ptr(OwnedPtr))
|
Some(deref_ptr(OwnedPtr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,12 +182,18 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
|
||||||
let kind = ty::BorrowKind::from_mutbl(mt.mutbl);
|
let kind = ty::BorrowKind::from_mutbl(mt.mutbl);
|
||||||
Some(deref_ptr(BorrowedPtr(kind, r)))
|
Some(deref_ptr(BorrowedPtr(kind, r)))
|
||||||
}
|
}
|
||||||
ty::ty_trait(~ty::TyTrait { store: ty::RegionTraitStore(r, mutbl), .. }) => {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
|
store: ty::RegionTraitStore(r, mutbl),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
let kind = ty::BorrowKind::from_mutbl(mutbl);
|
let kind = ty::BorrowKind::from_mutbl(mutbl);
|
||||||
Some(deref_ptr(BorrowedPtr(kind, r)))
|
Some(deref_ptr(BorrowedPtr(kind, r)))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(r, _), ..}) => {
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
|
store: ty::RegionTraitStore(r, _),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
Some(deref_ptr(BorrowedPtr(ty::ImmBorrow, r)))
|
Some(deref_ptr(BorrowedPtr(ty::ImmBorrow, r)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -650,7 +650,6 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor,
|
||||||
* | VariantName(..., P&, ...)
|
* | VariantName(..., P&, ...)
|
||||||
* | [ ..., P&, ... ]
|
* | [ ..., P&, ... ]
|
||||||
* | ( ..., P&, ... )
|
* | ( ..., P&, ... )
|
||||||
* | ~P&
|
|
||||||
* | box P&
|
* | box P&
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -704,7 +703,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor,
|
||||||
* | [ ..., E&, ... ]
|
* | [ ..., E&, ... ]
|
||||||
* | ( ..., E&, ... )
|
* | ( ..., E&, ... )
|
||||||
* | {...; E&}
|
* | {...; E&}
|
||||||
* | ~E&
|
* | box E&
|
||||||
* | E& as ...
|
* | E& as ...
|
||||||
* | ( E& )
|
* | ( E& )
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1155,7 +1155,7 @@ impl<'a> DynamicFailureHandler<'a> {
|
||||||
enum FailureHandler<'a> {
|
enum FailureHandler<'a> {
|
||||||
Infallible,
|
Infallible,
|
||||||
JumpToBasicBlock(BasicBlockRef),
|
JumpToBasicBlock(BasicBlockRef),
|
||||||
DynamicFailureHandlerClass(~DynamicFailureHandler<'a>),
|
DynamicFailureHandlerClass(Box<DynamicFailureHandler<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FailureHandler<'a> {
|
impl<'a> FailureHandler<'a> {
|
||||||
|
|
|
@ -248,9 +248,10 @@ pub fn is_ffi_safe(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
|
||||||
if hint.is_ffi_safe() {
|
if hint.is_ffi_safe() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Option<~T> and similar are used in FFI. Rather than try to resolve type parameters
|
// Option<Box<T>> and similar are used in FFI. Rather than try to
|
||||||
// and recognize this case exactly, this overapproximates -- assuming that if a
|
// resolve type parameters and recognize this case exactly, this
|
||||||
// non-C-like enum is being used in FFI then the user knows what they're doing.
|
// overapproximates -- assuming that if a non-C-like enum is being
|
||||||
|
// used in FFI then the user knows what they're doing.
|
||||||
if variants.iter().any(|vi| !vi.args.is_empty()) {
|
if variants.iter().any(|vi| !vi.args.is_empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ use middle::ty;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
|
|
||||||
pub struct CleanupScope<'a> {
|
pub struct CleanupScope<'a> {
|
||||||
// The id of this cleanup scope. If the id is None,
|
// The id of this cleanup scope. If the id is None,
|
||||||
// this is a *temporary scope* that is pushed during trans to
|
// this is a *temporary scope* that is pushed during trans to
|
||||||
|
@ -35,7 +36,7 @@ pub struct CleanupScope<'a> {
|
||||||
kind: CleanupScopeKind<'a>,
|
kind: CleanupScopeKind<'a>,
|
||||||
|
|
||||||
// Cleanups to run upon scope exit.
|
// Cleanups to run upon scope exit.
|
||||||
cleanups: Vec<~Cleanup>,
|
cleanups: Vec<Box<Cleanup>>,
|
||||||
|
|
||||||
cached_early_exits: Vec<CachedEarlyExit>,
|
cached_early_exits: Vec<CachedEarlyExit>,
|
||||||
cached_landing_pad: Option<BasicBlockRef>,
|
cached_landing_pad: Option<BasicBlockRef>,
|
||||||
|
@ -248,7 +249,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
|
||||||
self.ccx.tn.val_to_str(val),
|
self.ccx.tn.val_to_str(val),
|
||||||
ty.repr(self.ccx.tcx()));
|
ty.repr(self.ccx.tcx()));
|
||||||
|
|
||||||
self.schedule_clean(cleanup_scope, drop as ~Cleanup);
|
self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn schedule_drop_immediate(&self,
|
fn schedule_drop_immediate(&self,
|
||||||
|
@ -272,7 +273,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
|
||||||
self.ccx.tn.val_to_str(val),
|
self.ccx.tn.val_to_str(val),
|
||||||
ty.repr(self.ccx.tcx()));
|
ty.repr(self.ccx.tcx()));
|
||||||
|
|
||||||
self.schedule_clean(cleanup_scope, drop as ~Cleanup);
|
self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn schedule_free_value(&self,
|
fn schedule_free_value(&self,
|
||||||
|
@ -291,12 +292,12 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
|
||||||
self.ccx.tn.val_to_str(val),
|
self.ccx.tn.val_to_str(val),
|
||||||
heap);
|
heap);
|
||||||
|
|
||||||
self.schedule_clean(cleanup_scope, drop as ~Cleanup);
|
self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn schedule_clean(&self,
|
fn schedule_clean(&self,
|
||||||
cleanup_scope: ScopeId,
|
cleanup_scope: ScopeId,
|
||||||
cleanup: ~Cleanup) {
|
cleanup: Box<Cleanup>) {
|
||||||
match cleanup_scope {
|
match cleanup_scope {
|
||||||
AstScope(id) => self.schedule_clean_in_ast_scope(id, cleanup),
|
AstScope(id) => self.schedule_clean_in_ast_scope(id, cleanup),
|
||||||
CustomScope(id) => self.schedule_clean_in_custom_scope(id, cleanup),
|
CustomScope(id) => self.schedule_clean_in_custom_scope(id, cleanup),
|
||||||
|
@ -305,7 +306,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
|
||||||
|
|
||||||
fn schedule_clean_in_ast_scope(&self,
|
fn schedule_clean_in_ast_scope(&self,
|
||||||
cleanup_scope: ast::NodeId,
|
cleanup_scope: ast::NodeId,
|
||||||
cleanup: ~Cleanup) {
|
cleanup: Box<Cleanup>) {
|
||||||
/*!
|
/*!
|
||||||
* Schedules a cleanup to occur upon exit from `cleanup_scope`.
|
* Schedules a cleanup to occur upon exit from `cleanup_scope`.
|
||||||
* If `cleanup_scope` is not provided, then the cleanup is scheduled
|
* If `cleanup_scope` is not provided, then the cleanup is scheduled
|
||||||
|
@ -333,7 +334,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
|
||||||
|
|
||||||
fn schedule_clean_in_custom_scope(&self,
|
fn schedule_clean_in_custom_scope(&self,
|
||||||
custom_scope: CustomScopeIndex,
|
custom_scope: CustomScopeIndex,
|
||||||
cleanup: ~Cleanup) {
|
cleanup: Box<Cleanup>) {
|
||||||
/*!
|
/*!
|
||||||
* Schedules a cleanup to occur in the top-most scope,
|
* Schedules a cleanup to occur in the top-most scope,
|
||||||
* which must be a temporary scope.
|
* which must be a temporary scope.
|
||||||
|
@ -909,13 +910,13 @@ pub trait CleanupMethods<'a> {
|
||||||
heap: Heap);
|
heap: Heap);
|
||||||
fn schedule_clean(&self,
|
fn schedule_clean(&self,
|
||||||
cleanup_scope: ScopeId,
|
cleanup_scope: ScopeId,
|
||||||
cleanup: ~Cleanup);
|
cleanup: Box<Cleanup>);
|
||||||
fn schedule_clean_in_ast_scope(&self,
|
fn schedule_clean_in_ast_scope(&self,
|
||||||
cleanup_scope: ast::NodeId,
|
cleanup_scope: ast::NodeId,
|
||||||
cleanup: ~Cleanup);
|
cleanup: Box<Cleanup>);
|
||||||
fn schedule_clean_in_custom_scope(&self,
|
fn schedule_clean_in_custom_scope(&self,
|
||||||
custom_scope: CustomScopeIndex,
|
custom_scope: CustomScopeIndex,
|
||||||
cleanup: ~Cleanup);
|
cleanup: Box<Cleanup>);
|
||||||
fn needs_invoke(&self) -> bool;
|
fn needs_invoke(&self) -> bool;
|
||||||
fn get_landing_pad(&'a self) -> BasicBlockRef;
|
fn get_landing_pad(&'a self) -> BasicBlockRef;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ For example, the following simple type for a singly-linked list...
|
||||||
```
|
```
|
||||||
struct List {
|
struct List {
|
||||||
value: int,
|
value: int,
|
||||||
tail: Option<~List>,
|
tail: Option<Box<List>>,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ will generate the following callstack with a naive DFS algorithm:
|
||||||
```
|
```
|
||||||
describe(t = List)
|
describe(t = List)
|
||||||
describe(t = int)
|
describe(t = int)
|
||||||
describe(t = Option<~List>)
|
describe(t = Option<Box<List>>)
|
||||||
describe(t = ~List)
|
describe(t = Box<List>)
|
||||||
describe(t = List) // at the beginning again...
|
describe(t = List) // at the beginning again...
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
@ -211,7 +211,7 @@ pub struct FunctionDebugContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FunctionDebugContextRepr {
|
enum FunctionDebugContextRepr {
|
||||||
FunctionDebugContext(~FunctionDebugContextData),
|
FunctionDebugContext(Box<FunctionDebugContextData>),
|
||||||
DebugInfoDisabled,
|
DebugInfoDisabled,
|
||||||
FunctionWithoutDebugInfo,
|
FunctionWithoutDebugInfo,
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ enum FunctionDebugContextRepr {
|
||||||
impl FunctionDebugContext {
|
impl FunctionDebugContext {
|
||||||
fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
|
fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
|
||||||
match self.repr {
|
match self.repr {
|
||||||
FunctionDebugContext(~ref data) => data,
|
FunctionDebugContext(box ref data) => data,
|
||||||
DebugInfoDisabled => {
|
DebugInfoDisabled => {
|
||||||
cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
|
cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
|
||||||
}
|
}
|
||||||
|
@ -560,7 +560,7 @@ pub fn set_source_location(fcx: &FunctionContext,
|
||||||
set_debug_location(fcx.ccx, UnknownLocation);
|
set_debug_location(fcx.ccx, UnknownLocation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FunctionDebugContext(~ref function_debug_context) => {
|
FunctionDebugContext(box ref function_debug_context) => {
|
||||||
let cx = fcx.ccx;
|
let cx = fcx.ccx;
|
||||||
|
|
||||||
debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
|
debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
|
||||||
|
@ -596,7 +596,7 @@ pub fn clear_source_location(fcx: &FunctionContext) {
|
||||||
/// translated.
|
/// translated.
|
||||||
pub fn start_emitting_source_locations(fcx: &FunctionContext) {
|
pub fn start_emitting_source_locations(fcx: &FunctionContext) {
|
||||||
match fcx.debug_context.repr {
|
match fcx.debug_context.repr {
|
||||||
FunctionDebugContext(~ref data) => {
|
FunctionDebugContext(box ref data) => {
|
||||||
data.source_locations_enabled.set(true)
|
data.source_locations_enabled.set(true)
|
||||||
},
|
},
|
||||||
_ => { /* safe to ignore */ }
|
_ => { /* safe to ignore */ }
|
||||||
|
@ -2227,7 +2227,12 @@ fn type_metadata(cx: &CrateContext,
|
||||||
ty::ty_closure(ref closurety) => {
|
ty::ty_closure(ref closurety) => {
|
||||||
subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
|
subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
|
||||||
}
|
}
|
||||||
ty::ty_trait(~ty::TyTrait { def_id, ref substs, store, ref bounds }) => {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
|
def_id,
|
||||||
|
ref substs,
|
||||||
|
store,
|
||||||
|
ref bounds
|
||||||
|
}) => {
|
||||||
trait_metadata(cx, def_id, t, substs, store, bounds)
|
trait_metadata(cx, def_id, t, substs, store, bounds)
|
||||||
}
|
}
|
||||||
ty::ty_struct(def_id, ref substs) => {
|
ty::ty_struct(def_id, ref substs) => {
|
||||||
|
|
|
@ -31,7 +31,7 @@ expression functions depending on the kind of expression. We divide
|
||||||
up expressions into:
|
up expressions into:
|
||||||
|
|
||||||
- **Datum expressions:** Those that most naturally yield values.
|
- **Datum expressions:** Those that most naturally yield values.
|
||||||
Examples would be `22`, `~x`, or `a + b` (when not overloaded).
|
Examples would be `22`, `box x`, or `a + b` (when not overloaded).
|
||||||
- **DPS expressions:** Those that most naturally write into a location
|
- **DPS expressions:** Those that most naturally write into a location
|
||||||
in memory. Examples would be `foo()` or `Point { x: 3, y: 4 }`.
|
in memory. Examples would be `foo()` or `Point { x: 3, y: 4 }`.
|
||||||
- **Statement expressions:** That that do not generate a meaningful
|
- **Statement expressions:** That that do not generate a meaningful
|
||||||
|
@ -107,7 +107,7 @@ Somewhat surprisingly, not all lvalue expressions yield lvalue datums
|
||||||
when trans'd. Ultimately the reason for this is to micro-optimize
|
when trans'd. Ultimately the reason for this is to micro-optimize
|
||||||
the resulting LLVM. For example, consider the following code:
|
the resulting LLVM. For example, consider the following code:
|
||||||
|
|
||||||
fn foo() -> ~int { ... }
|
fn foo() -> Box<int> { ... }
|
||||||
let x = *foo();
|
let x = *foo();
|
||||||
|
|
||||||
The expression `*foo()` is an lvalue, but if you invoke `expr::trans`,
|
The expression `*foo()` is an lvalue, but if you invoke `expr::trans`,
|
||||||
|
@ -169,7 +169,7 @@ is fully initialized, then the cleanup will run and try to free or
|
||||||
drop uninitialized memory. If the initialization itself produces
|
drop uninitialized memory. If the initialization itself produces
|
||||||
byproducts that need to be freed, then you should use temporary custom
|
byproducts that need to be freed, then you should use temporary custom
|
||||||
scopes to ensure that those byproducts will get freed on unwind. For
|
scopes to ensure that those byproducts will get freed on unwind. For
|
||||||
example, an expression like `~foo()` will first allocate a box in the
|
example, an expression like `box foo()` will first allocate a box in the
|
||||||
heap and then call `foo()` -- if `foo()` should fail, this box needs
|
heap and then call `foo()` -- if `foo()` should fail, this box needs
|
||||||
to be *shallowly* freed.
|
to be *shallowly* freed.
|
||||||
|
|
||||||
|
@ -219,11 +219,11 @@ unwind, and only up until the point where execution succeeded, at
|
||||||
which time the complete value should be stored in an lvalue or some
|
which time the complete value should be stored in an lvalue or some
|
||||||
other place where normal cleanup applies.
|
other place where normal cleanup applies.
|
||||||
|
|
||||||
To spell it out, here is an example. Imagine an expression `~expr`.
|
To spell it out, here is an example. Imagine an expression `box expr`.
|
||||||
We would basically:
|
We would basically:
|
||||||
|
|
||||||
1. Push a custom cleanup scope C.
|
1. Push a custom cleanup scope C.
|
||||||
2. Allocate the `~` box.
|
2. Allocate the box.
|
||||||
3. Schedule a shallow free in the scope C.
|
3. Schedule a shallow free in the scope C.
|
||||||
4. Trans `expr` into the box.
|
4. Trans `expr` into the box.
|
||||||
5. Pop the scope C.
|
5. Pop the scope C.
|
||||||
|
|
|
@ -397,8 +397,8 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
|
||||||
DatumBlock(bcx, datum)
|
DatumBlock(bcx, datum)
|
||||||
}
|
}
|
||||||
ast::ExprBox(_, contents) => {
|
ast::ExprBox(_, contents) => {
|
||||||
// Special case for `~T`. (The other case, for GC, is handled in
|
// Special case for `box T`. (The other case, for GC, is handled
|
||||||
// `trans_rvalue_dps_unadjusted`.)
|
// in `trans_rvalue_dps_unadjusted`.)
|
||||||
let box_ty = expr_ty(bcx, expr);
|
let box_ty = expr_ty(bcx, expr);
|
||||||
let contents_ty = expr_ty(bcx, contents);
|
let contents_ty = expr_ty(bcx, contents);
|
||||||
trans_uniq_expr(bcx, box_ty, contents, contents_ty)
|
trans_uniq_expr(bcx, box_ty, contents, contents_ty)
|
||||||
|
@ -1171,11 +1171,12 @@ fn trans_uniq_expr<'a>(bcx: &'a Block<'a>,
|
||||||
let llty = type_of::type_of(bcx.ccx(), contents_ty);
|
let llty = type_of::type_of(bcx.ccx(), contents_ty);
|
||||||
let size = llsize_of(bcx.ccx(), llty);
|
let size = llsize_of(bcx.ccx(), llty);
|
||||||
// We need to a make a pointer type because box_ty is ty_bot
|
// We need to a make a pointer type because box_ty is ty_bot
|
||||||
// if content_ty is, e.g. ~fail!().
|
// if content_ty is, e.g. box fail!().
|
||||||
let real_box_ty = ty::mk_uniq(bcx.tcx(), contents_ty);
|
let real_box_ty = ty::mk_uniq(bcx.tcx(), contents_ty);
|
||||||
let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size);
|
let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size);
|
||||||
// Unique boxes do not allocate for zero-size types. The standard library may assume
|
// Unique boxes do not allocate for zero-size types. The standard library
|
||||||
// that `free` is never called on the pointer returned for `~ZeroSizeType`.
|
// may assume that `free` is never called on the pointer returned for
|
||||||
|
// `Box<ZeroSizeType>`.
|
||||||
let bcx = if llsize_of_alloc(bcx.ccx(), llty) == 0 {
|
let bcx = if llsize_of_alloc(bcx.ccx(), llty) == 0 {
|
||||||
trans_into(bcx, contents, SaveIn(val))
|
trans_into(bcx, contents, SaveIn(val))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1774,8 +1775,8 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
|
||||||
* Basically, the idea is to make the deref of an rvalue
|
* Basically, the idea is to make the deref of an rvalue
|
||||||
* result in an rvalue. This helps to avoid intermediate stack
|
* result in an rvalue. This helps to avoid intermediate stack
|
||||||
* slots in the resulting LLVM. The idea here is that, if the
|
* slots in the resulting LLVM. The idea here is that, if the
|
||||||
* `~T` pointer is an rvalue, then we can schedule a *shallow*
|
* `Box<T>` pointer is an rvalue, then we can schedule a *shallow*
|
||||||
* free of the `~T` pointer, and then return a ByRef rvalue
|
* free of the `Box<T>` pointer, and then return a ByRef rvalue
|
||||||
* into the pointer. Because the free is shallow, it is legit
|
* into the pointer. Because the free is shallow, it is legit
|
||||||
* to return an rvalue, because we know that the contents are
|
* to return an rvalue, because we know that the contents are
|
||||||
* not yet scheduled to be freed. The language rules ensure that the
|
* not yet scheduled to be freed. The language rules ensure that the
|
||||||
|
|
|
@ -89,7 +89,7 @@ fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t {
|
||||||
let llty = sizing_type_of(ccx, typ);
|
let llty = sizing_type_of(ccx, typ);
|
||||||
// Unique boxes do not allocate for zero-size types. The standard
|
// Unique boxes do not allocate for zero-size types. The standard
|
||||||
// library may assume that `free` is never called on the pointer
|
// library may assume that `free` is never called on the pointer
|
||||||
// returned for `~ZeroSizeType`.
|
// returned for `Box<ZeroSizeType>`.
|
||||||
if llsize_of_alloc(ccx, llty) == 0 {
|
if llsize_of_alloc(ccx, llty) == 0 {
|
||||||
ty::mk_i8()
|
ty::mk_i8()
|
||||||
} else {
|
} else {
|
||||||
|
@ -318,7 +318,7 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) => {
|
ty::ty_trait(box ty::TyTrait { store: ty::UniqTraitStore, .. }) => {
|
||||||
let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
|
let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
|
||||||
// Only drop the value when it is non-null
|
// Only drop the value when it is non-null
|
||||||
with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue)), |bcx| {
|
with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue)), |bcx| {
|
||||||
|
|
|
@ -344,7 +344,7 @@ fn trans_trait_callee<'a>(bcx: &'a Block<'a>,
|
||||||
-> Callee<'a> {
|
-> Callee<'a> {
|
||||||
/*!
|
/*!
|
||||||
* Create a method callee where the method is coming from a trait
|
* Create a method callee where the method is coming from a trait
|
||||||
* object (e.g., ~Trait type). In this case, we must pull the fn
|
* object (e.g., Box<Trait> type). In this case, we must pull the fn
|
||||||
* pointer out of the vtable that is packaged up with the object.
|
* pointer out of the vtable that is packaged up with the object.
|
||||||
* Objects are represented as a pair, so we first evaluate the self
|
* Objects are represented as a pair, so we first evaluate the self
|
||||||
* expression and then extract the self data and vtable out of the
|
* expression and then extract the self data and vtable out of the
|
||||||
|
@ -401,7 +401,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
|
||||||
|
|
||||||
// Load the function from the vtable and cast it to the expected type.
|
// Load the function from the vtable and cast it to the expected type.
|
||||||
debug!("(translating trait callee) loading method");
|
debug!("(translating trait callee) loading method");
|
||||||
// Replace the self type (&Self or ~Self) with an opaque pointer.
|
// Replace the self type (&Self or Box<Self>) with an opaque pointer.
|
||||||
let llcallee_ty = match ty::get(callee_ty).sty {
|
let llcallee_ty = match ty::get(callee_ty).sty {
|
||||||
ty::ty_bare_fn(ref f) if f.abi == Rust => {
|
ty::ty_bare_fn(ref f) if f.abi == Rust => {
|
||||||
type_of_rust_fn(ccx, true, f.sig.inputs.slice_from(1), f.sig.output)
|
type_of_rust_fn(ccx, true, f.sig.inputs.slice_from(1), f.sig.output)
|
||||||
|
@ -527,8 +527,8 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
|
||||||
dest: expr::Dest)
|
dest: expr::Dest)
|
||||||
-> &'a Block<'a> {
|
-> &'a Block<'a> {
|
||||||
/*!
|
/*!
|
||||||
* Generates the code to convert from a pointer (`~T`, `&T`, etc)
|
* Generates the code to convert from a pointer (`Box<T>`, `&T`, etc)
|
||||||
* into an object (`~Trait`, `&Trait`, etc). This means creating a
|
* into an object (`Box<Trait>`, `&Trait`, etc). This means creating a
|
||||||
* pair where the first word is the vtable and the second word is
|
* pair where the first word is the vtable and the second word is
|
||||||
* the pointer.
|
* the pointer.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -128,7 +128,7 @@ pub struct mt {
|
||||||
|
|
||||||
#[deriving(Clone, Eq, TotalEq, Hash, Encodable, Decodable, Show)]
|
#[deriving(Clone, Eq, TotalEq, Hash, Encodable, Decodable, Show)]
|
||||||
pub enum TraitStore {
|
pub enum TraitStore {
|
||||||
/// ~Trait
|
/// Box<Trait>
|
||||||
UniqTraitStore,
|
UniqTraitStore,
|
||||||
/// &Trait and &mut Trait
|
/// &Trait and &mut Trait
|
||||||
RegionTraitStore(Region, ast::Mutability),
|
RegionTraitStore(Region, ast::Mutability),
|
||||||
|
@ -229,7 +229,7 @@ pub enum AutoRef {
|
||||||
/// Convert from T to *T
|
/// Convert from T to *T
|
||||||
AutoUnsafe(ast::Mutability),
|
AutoUnsafe(ast::Mutability),
|
||||||
|
|
||||||
/// Convert from ~Trait/&Trait to &Trait
|
/// Convert from Box<Trait>/&Trait to &Trait
|
||||||
AutoBorrowObj(Region, ast::Mutability),
|
AutoBorrowObj(Region, ast::Mutability),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ pub enum AutoRef {
|
||||||
pub struct ctxt {
|
pub struct ctxt {
|
||||||
// Specifically use a speedy hash algorithm for this hash map, it's used
|
// Specifically use a speedy hash algorithm for this hash map, it's used
|
||||||
// quite often.
|
// quite often.
|
||||||
pub interner: RefCell<FnvHashMap<intern_key, ~t_box_>>,
|
pub interner: RefCell<FnvHashMap<intern_key, Box<t_box_>>>,
|
||||||
pub next_id: Cell<uint>,
|
pub next_id: Cell<uint>,
|
||||||
pub sess: Session,
|
pub sess: Session,
|
||||||
pub def_map: resolve::DefMap,
|
pub def_map: resolve::DefMap,
|
||||||
|
@ -735,8 +735,8 @@ pub enum sty {
|
||||||
ty_ptr(mt),
|
ty_ptr(mt),
|
||||||
ty_rptr(Region, mt),
|
ty_rptr(Region, mt),
|
||||||
ty_bare_fn(BareFnTy),
|
ty_bare_fn(BareFnTy),
|
||||||
ty_closure(~ClosureTy),
|
ty_closure(Box<ClosureTy>),
|
||||||
ty_trait(~TyTrait),
|
ty_trait(Box<TyTrait>),
|
||||||
ty_struct(DefId, substs),
|
ty_struct(DefId, substs),
|
||||||
ty_tup(Vec<t>),
|
ty_tup(Vec<t>),
|
||||||
|
|
||||||
|
@ -1195,7 +1195,7 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
|
||||||
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
|
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
|
||||||
flags |= sflags(substs);
|
flags |= sflags(substs);
|
||||||
}
|
}
|
||||||
&ty_trait(~ty::TyTrait { ref substs, store, .. }) => {
|
&ty_trait(box ty::TyTrait { ref substs, store, .. }) => {
|
||||||
flags |= sflags(substs);
|
flags |= sflags(substs);
|
||||||
match store {
|
match store {
|
||||||
RegionTraitStore(r, _) => {
|
RegionTraitStore(r, _) => {
|
||||||
|
@ -1482,7 +1482,7 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
|
||||||
maybe_walk_ty(tm.ty, f);
|
maybe_walk_ty(tm.ty, f);
|
||||||
}
|
}
|
||||||
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
|
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
|
||||||
ty_trait(~TyTrait { ref substs, .. }) => {
|
ty_trait(box TyTrait { ref substs, .. }) => {
|
||||||
for subty in (*substs).tps.iter() { maybe_walk_ty(*subty, |x| f(x)); }
|
for subty in (*substs).tps.iter() { maybe_walk_ty(*subty, |x| f(x)); }
|
||||||
}
|
}
|
||||||
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
|
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
|
||||||
|
@ -1951,7 +1951,7 @@ impl TypeContents {
|
||||||
pub fn owned_pointer(&self) -> TypeContents {
|
pub fn owned_pointer(&self) -> TypeContents {
|
||||||
/*!
|
/*!
|
||||||
* Includes only those bits that still apply
|
* Includes only those bits that still apply
|
||||||
* when indirected through a `~` pointer
|
* when indirected through a `Box` pointer
|
||||||
*/
|
*/
|
||||||
TC::OwnsOwned | (
|
TC::OwnsOwned | (
|
||||||
*self & (TC::OwnsAll | TC::ReachesAll))
|
*self & (TC::OwnsAll | TC::ReachesAll))
|
||||||
|
@ -2050,7 +2050,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
|
||||||
// private cache for this walk. This is needed in the case of cyclic
|
// private cache for this walk. This is needed in the case of cyclic
|
||||||
// types like:
|
// types like:
|
||||||
//
|
//
|
||||||
// struct List { next: ~Option<List>, ... }
|
// struct List { next: Box<Option<List>>, ... }
|
||||||
//
|
//
|
||||||
// When computing the type contents of such a type, we wind up deeply
|
// When computing the type contents of such a type, we wind up deeply
|
||||||
// recursing as we go. So when we encounter the recursive reference
|
// recursing as we go. So when we encounter the recursive reference
|
||||||
|
@ -2100,7 +2100,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty_trait(~ty::TyTrait { store, bounds, .. }) => {
|
ty_trait(box ty::TyTrait { store, bounds, .. }) => {
|
||||||
object_contents(cx, store, bounds)
|
object_contents(cx, store, bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2965,7 +2965,7 @@ pub fn adjust_ty(cx: &ctxt,
|
||||||
fn borrow_obj(cx: &ctxt, span: Span, r: Region,
|
fn borrow_obj(cx: &ctxt, span: Span, r: Region,
|
||||||
m: ast::Mutability, ty: ty::t) -> ty::t {
|
m: ast::Mutability, ty: ty::t) -> ty::t {
|
||||||
match get(ty).sty {
|
match get(ty).sty {
|
||||||
ty_trait(~ty::TyTrait {def_id, ref substs, bounds, .. }) => {
|
ty_trait(box ty::TyTrait {def_id, ref substs, bounds, .. }) => {
|
||||||
ty::mk_trait(cx, def_id, substs.clone(),
|
ty::mk_trait(cx, def_id, substs.clone(),
|
||||||
RegionTraitStore(r, m), bounds)
|
RegionTraitStore(r, m), bounds)
|
||||||
}
|
}
|
||||||
|
@ -3164,7 +3164,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
||||||
// writing) it's not easy to distinguish casts to traits
|
// writing) it's not easy to distinguish casts to traits
|
||||||
// from other casts based on the AST. This should be
|
// from other casts based on the AST. This should be
|
||||||
// easier in the future, when casts to traits
|
// easier in the future, when casts to traits
|
||||||
// would like @Foo, ~Foo, or &Foo.
|
// would like @Foo, Box<Foo>, or &Foo.
|
||||||
RvalueDatumExpr
|
RvalueDatumExpr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3192,7 +3192,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprBox(place, _) => {
|
ast::ExprBox(place, _) => {
|
||||||
// Special case `~T` for now:
|
// Special case `Box<T>` for now:
|
||||||
let definition = match tcx.def_map.borrow().find(&place.id) {
|
let definition = match tcx.def_map.borrow().find(&place.id) {
|
||||||
Some(&def) => def,
|
Some(&def) => def,
|
||||||
None => fail!("no def for place"),
|
None => fail!("no def for place"),
|
||||||
|
@ -3264,7 +3264,7 @@ pub fn ty_sort_str(cx: &ctxt, t: t) -> ~str {
|
||||||
|
|
||||||
ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
|
ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
|
||||||
ty_box(_) => "@-ptr".to_owned(),
|
ty_box(_) => "@-ptr".to_owned(),
|
||||||
ty_uniq(_) => "~-ptr".to_owned(),
|
ty_uniq(_) => "box".to_owned(),
|
||||||
ty_vec(_, _) => "vector".to_owned(),
|
ty_vec(_, _) => "vector".to_owned(),
|
||||||
ty_ptr(_) => "*-ptr".to_owned(),
|
ty_ptr(_) => "*-ptr".to_owned(),
|
||||||
ty_rptr(_, _) => "&-ptr".to_owned(),
|
ty_rptr(_, _) => "&-ptr".to_owned(),
|
||||||
|
@ -3614,7 +3614,9 @@ pub fn try_add_builtin_trait(tcx: &ctxt,
|
||||||
|
|
||||||
pub fn ty_to_def_id(ty: t) -> Option<ast::DefId> {
|
pub fn ty_to_def_id(ty: t) -> Option<ast::DefId> {
|
||||||
match get(ty).sty {
|
match get(ty).sty {
|
||||||
ty_trait(~TyTrait { def_id: id, .. }) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
|
ty_trait(box TyTrait { def_id: id, .. }) |
|
||||||
|
ty_struct(id, _) |
|
||||||
|
ty_enum(id, _) => Some(id),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4575,7 +4577,7 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty_trait(~ty::TyTrait { def_id: d, store, bounds, .. }) => {
|
ty_trait(box ty::TyTrait { def_id: d, store, bounds, .. }) => {
|
||||||
byte!(17);
|
byte!(17);
|
||||||
did(&mut state, d);
|
did(&mut state, d);
|
||||||
match store {
|
match store {
|
||||||
|
|
|
@ -149,8 +149,13 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
|
||||||
ty::ty_enum(tid, ref substs) => {
|
ty::ty_enum(tid, ref substs) => {
|
||||||
ty::ty_enum(tid, this.fold_substs(substs))
|
ty::ty_enum(tid, this.fold_substs(substs))
|
||||||
}
|
}
|
||||||
ty::ty_trait(~ty::TyTrait { def_id, ref substs, store, bounds }) => {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
ty::ty_trait(box ty::TyTrait{
|
def_id,
|
||||||
|
ref substs,
|
||||||
|
store,
|
||||||
|
bounds
|
||||||
|
}) => {
|
||||||
|
ty::ty_trait(box ty::TyTrait {
|
||||||
def_id: def_id,
|
def_id: def_id,
|
||||||
substs: this.fold_substs(substs),
|
substs: this.fold_substs(substs),
|
||||||
store: this.fold_trait_store(store),
|
store: this.fold_trait_store(store),
|
||||||
|
|
|
@ -876,7 +876,8 @@ fn conv_builtin_bounds(tcx: &ty::ctxt, ast_bounds: &Option<OwnedSlice<ast::TyPar
|
||||||
//! legal.
|
//! legal.
|
||||||
//! If no bounds were specified, we choose a "default" bound based on
|
//! If no bounds were specified, we choose a "default" bound based on
|
||||||
//! the allocation type of the fn/trait, as per issue #7264. The user can
|
//! the allocation type of the fn/trait, as per issue #7264. The user can
|
||||||
//! override this with an empty bounds list, e.g. "~fn:()" or "~Trait:".
|
//! override this with an empty bounds list, e.g. "Box<fn:()>" or
|
||||||
|
//! "Box<Trait:>".
|
||||||
|
|
||||||
match (ast_bounds, store) {
|
match (ast_bounds, store) {
|
||||||
(&Some(ref bound_vec), _) => {
|
(&Some(ref bound_vec), _) => {
|
||||||
|
|
|
@ -691,7 +691,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to check @, ~ and & patterns
|
// Helper function to check @, box and & patterns
|
||||||
pub fn check_pointer_pat(pcx: &pat_ctxt,
|
pub fn check_pointer_pat(pcx: &pat_ctxt,
|
||||||
pointer_kind: PointerKind,
|
pointer_kind: PointerKind,
|
||||||
inner: &ast::Pat,
|
inner: &ast::Pat,
|
||||||
|
@ -721,7 +721,7 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
|
||||||
e, actual)})},
|
e, actual)})},
|
||||||
Some(expected),
|
Some(expected),
|
||||||
format!("{} pattern", match pointer_kind {
|
format!("{} pattern", match pointer_kind {
|
||||||
Send => "a `~`-box",
|
Send => "a box",
|
||||||
Borrowed => "an `&`-pointer"
|
Borrowed => "an `&`-pointer"
|
||||||
}),
|
}),
|
||||||
None);
|
None);
|
||||||
|
|
|
@ -30,7 +30,7 @@ itself (note that inherent impls can only be defined in the same
|
||||||
module as the type itself).
|
module as the type itself).
|
||||||
|
|
||||||
Inherent candidates are not always derived from impls. If you have a
|
Inherent candidates are not always derived from impls. If you have a
|
||||||
trait instance, such as a value of type `~ToStr`, then the trait
|
trait instance, such as a value of type `Box<ToStr>`, then the trait
|
||||||
methods (`to_str()`, in this case) are inherently associated with it.
|
methods (`to_str()`, in this case) are inherently associated with it.
|
||||||
Another case is type parameters, in which case the methods of their
|
Another case is type parameters, in which case the methods of their
|
||||||
bounds are inherent.
|
bounds are inherent.
|
||||||
|
@ -72,9 +72,9 @@ Both the inherent candidate collection and the candidate selection
|
||||||
proceed by progressively deref'ing the receiver type, after all. The
|
proceed by progressively deref'ing the receiver type, after all. The
|
||||||
answer is that two phases are needed to elegantly deal with explicit
|
answer is that two phases are needed to elegantly deal with explicit
|
||||||
self. After all, if there is an impl for the type `Foo`, it can
|
self. After all, if there is an impl for the type `Foo`, it can
|
||||||
define a method with the type `~self`, which means that it expects a
|
define a method with the type `Box<self>`, which means that it expects a
|
||||||
receiver of type `~Foo`. If we have a receiver of type `~Foo`, but we
|
receiver of type `Box<Foo>`. If we have a receiver of type `Box<Foo>`, but we
|
||||||
waited to search for that impl until we have deref'd the `~` away and
|
waited to search for that impl until we have deref'd the `Box` away and
|
||||||
obtained the type `Foo`, we would never match this method.
|
obtained the type `Foo`, we would never match this method.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -243,15 +243,15 @@ fn construct_transformed_self_ty_for_object(
|
||||||
*
|
*
|
||||||
* trait Foo {
|
* trait Foo {
|
||||||
* fn r_method<'a>(&'a self);
|
* fn r_method<'a>(&'a self);
|
||||||
* fn u_method(~self);
|
* fn u_method(Box<self>);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* Now, assuming that `r_method` is being called, we want the
|
* Now, assuming that `r_method` is being called, we want the
|
||||||
* result to be `&'a Foo`. Assuming that `u_method` is being
|
* result to be `&'a Foo`. Assuming that `u_method` is being
|
||||||
* called, we want the result to be `~Foo`. Of course,
|
* called, we want the result to be `Box<Foo>`. Of course,
|
||||||
* this transformation has already been done as part of
|
* this transformation has already been done as part of
|
||||||
* `method_ty.fty.sig.inputs[0]`, but there the type
|
* `method_ty.fty.sig.inputs[0]`, but there the type
|
||||||
* is expressed in terms of `Self` (i.e., `&'a Self`, `~Self`).
|
* is expressed in terms of `Self` (i.e., `&'a Self`, `Box<Self>`).
|
||||||
* Because objects are not standalone types, we can't just substitute
|
* Because objects are not standalone types, we can't just substitute
|
||||||
* `s/Self/Foo/`, so we must instead perform this kind of hokey
|
* `s/Self/Foo/`, so we must instead perform this kind of hokey
|
||||||
* match below.
|
* match below.
|
||||||
|
@ -328,8 +328,8 @@ struct Candidate {
|
||||||
/// considered to "match" a given method candidate. Typically the test
|
/// considered to "match" a given method candidate. Typically the test
|
||||||
/// is whether the receiver is of a particular type. However, this
|
/// is whether the receiver is of a particular type. However, this
|
||||||
/// type is the type of the receiver *after accounting for the
|
/// type is the type of the receiver *after accounting for the
|
||||||
/// method's self type* (e.g., if the method is an `~self` method, we
|
/// method's self type* (e.g., if the method is an `Box<self>` method, we
|
||||||
/// have *already verified* that the receiver is of some type `~T` and
|
/// have *already verified* that the receiver is of some type `Box<T>` and
|
||||||
/// now we must check that the type `T` is correct). Unfortunately,
|
/// now we must check that the type `T` is correct). Unfortunately,
|
||||||
/// because traits are not types, this is a pain to do.
|
/// because traits are not types, this is a pain to do.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
|
@ -421,14 +421,14 @@ impl<'a> LookupContext<'a> {
|
||||||
* `self.inherent_candidates`. See comment at the start of
|
* `self.inherent_candidates`. See comment at the start of
|
||||||
* the file. To find the inherent candidates, we repeatedly
|
* the file. To find the inherent candidates, we repeatedly
|
||||||
* deref the self-ty to find the "base-type". So, for
|
* deref the self-ty to find the "base-type". So, for
|
||||||
* example, if the receiver is ~~C where `C` is a struct type,
|
* example, if the receiver is Box<Box<C>> where `C` is a struct type,
|
||||||
* we'll want to find the inherent impls for `C`.
|
* we'll want to find the inherent impls for `C`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let span = self.self_expr.map_or(self.span, |e| e.span);
|
let span = self.self_expr.map_or(self.span, |e| e.span);
|
||||||
check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
|
check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
|
||||||
match get(self_ty).sty {
|
match get(self_ty).sty {
|
||||||
ty_trait(~TyTrait { def_id, ref substs, .. }) => {
|
ty_trait(box TyTrait { def_id, ref substs, .. }) => {
|
||||||
self.push_inherent_candidates_from_object(def_id, substs);
|
self.push_inherent_candidates_from_object(def_id, substs);
|
||||||
self.push_inherent_impl_candidates_for_type(def_id);
|
self.push_inherent_impl_candidates_for_type(def_id);
|
||||||
}
|
}
|
||||||
|
@ -767,9 +767,9 @@ impl<'a> LookupContext<'a> {
|
||||||
* consuming the original pointer.
|
* consuming the original pointer.
|
||||||
*
|
*
|
||||||
* You might think that this would be a natural byproduct of
|
* You might think that this would be a natural byproduct of
|
||||||
* the auto-deref/auto-ref process. This is true for `~T`
|
* the auto-deref/auto-ref process. This is true for `Box<T>`
|
||||||
* but not for an `&mut T` receiver. With `~T`, we would
|
* but not for an `&mut T` receiver. With `Box<T>`, we would
|
||||||
* begin by testing for methods with a self type `~T`,
|
* begin by testing for methods with a self type `Box<T>`,
|
||||||
* then autoderef to `T`, then autoref to `&mut T`. But with
|
* then autoderef to `T`, then autoref to `&mut T`. But with
|
||||||
* an `&mut T` receiver the process begins with `&mut T`, only
|
* an `&mut T` receiver the process begins with `&mut T`, only
|
||||||
* without any autoadjustments.
|
* without any autoadjustments.
|
||||||
|
@ -797,7 +797,7 @@ impl<'a> LookupContext<'a> {
|
||||||
autoref: Some(auto)})
|
autoref: Some(auto)})
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_trait(~ty::TyTrait {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
def_id, ref substs, store: ty::RegionTraitStore(_, mutbl), bounds
|
def_id, ref substs, store: ty::RegionTraitStore(_, mutbl), bounds
|
||||||
}) => {
|
}) => {
|
||||||
let region =
|
let region =
|
||||||
|
@ -902,8 +902,13 @@ impl<'a> LookupContext<'a> {
|
||||||
},
|
},
|
||||||
ty_vec(mt, Some(_)) => self.auto_slice_vec(mt, autoderefs),
|
ty_vec(mt, Some(_)) => self.auto_slice_vec(mt, autoderefs),
|
||||||
|
|
||||||
ty_trait(~ty::TyTrait { def_id: trt_did, substs: trt_substs, bounds: b, .. }) => {
|
ty_trait(box ty::TyTrait {
|
||||||
// Coerce ~/&Trait instances to &Trait.
|
def_id: trt_did,
|
||||||
|
substs: trt_substs,
|
||||||
|
bounds: b,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
// Coerce Box/&Trait instances to &Trait.
|
||||||
|
|
||||||
self.search_for_some_kind_of_autorefd_method(
|
self.search_for_some_kind_of_autorefd_method(
|
||||||
AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
|
AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
|
||||||
|
@ -1361,7 +1366,7 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_trait(~ty::TyTrait {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
def_id: self_did, store: RegionTraitStore(_, self_m), ..
|
def_id: self_did, store: RegionTraitStore(_, self_m), ..
|
||||||
}) => {
|
}) => {
|
||||||
mutability_matches(self_m, m) &&
|
mutability_matches(self_m, m) &&
|
||||||
|
@ -1382,7 +1387,7 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_trait(~ty::TyTrait {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
def_id: self_did, store: UniqTraitStore, ..
|
def_id: self_did, store: UniqTraitStore, ..
|
||||||
}) => {
|
}) => {
|
||||||
rcvr_matches_object(self_did, candidate)
|
rcvr_matches_object(self_did, candidate)
|
||||||
|
|
|
@ -1912,7 +1912,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||||
|
|
||||||
let fn_sig = match *fn_sty {
|
let fn_sig = match *fn_sty {
|
||||||
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
|
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
|
||||||
ty::ty_closure(~ty::ClosureTy {sig: ref sig, ..}) => sig,
|
ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
|
||||||
_ => {
|
_ => {
|
||||||
fcx.type_error_message(call_expr.span, |actual| {
|
fcx.type_error_message(call_expr.span, |actual| {
|
||||||
format!("expected function but \
|
format!("expected function but \
|
||||||
|
|
|
@ -367,7 +367,7 @@ fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
|
||||||
// accessed. We must be wary of loops like this:
|
// accessed. We must be wary of loops like this:
|
||||||
//
|
//
|
||||||
// // from src/test/compile-fail/borrowck-lend-flow.rs
|
// // from src/test/compile-fail/borrowck-lend-flow.rs
|
||||||
// let mut v = ~3, w = ~4;
|
// let mut v = box 3, w = box 4;
|
||||||
// let mut x = &mut w;
|
// let mut x = &mut w;
|
||||||
// loop {
|
// loop {
|
||||||
// **x += 1; // (2)
|
// **x += 1; // (2)
|
||||||
|
@ -539,7 +539,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
|
||||||
// explaining how it goes about doing that.
|
// explaining how it goes about doing that.
|
||||||
let target_ty = rcx.resolve_node_type(expr.id);
|
let target_ty = rcx.resolve_node_type(expr.id);
|
||||||
match ty::get(target_ty).sty {
|
match ty::get(target_ty).sty {
|
||||||
ty::ty_trait(~ty::TyTrait {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
store: ty::RegionTraitStore(trait_region, _), ..
|
store: ty::RegionTraitStore(trait_region, _), ..
|
||||||
}) => {
|
}) => {
|
||||||
let source_ty = rcx.resolve_expr_type_adjusted(source);
|
let source_ty = rcx.resolve_expr_type_adjusted(source);
|
||||||
|
@ -609,7 +609,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
|
||||||
let tcx = rcx.fcx.tcx();
|
let tcx = rcx.fcx.tcx();
|
||||||
let function_type = rcx.resolve_node_type(expr.id);
|
let function_type = rcx.resolve_node_type(expr.id);
|
||||||
match ty::get(function_type).sty {
|
match ty::get(function_type).sty {
|
||||||
ty::ty_closure(~ty::ClosureTy {
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
store: ty::RegionTraitStore(region, _), ..}) => {
|
store: ty::RegionTraitStore(region, _), ..}) => {
|
||||||
freevars::with_freevars(tcx, expr.id, |freevars| {
|
freevars::with_freevars(tcx, expr.id, |freevars| {
|
||||||
if freevars.is_empty() {
|
if freevars.is_empty() {
|
||||||
|
@ -635,7 +635,10 @@ fn check_expr_fn_block(rcx: &mut Rcx,
|
||||||
rcx.set_repeating_scope(repeating_scope);
|
rcx.set_repeating_scope(repeating_scope);
|
||||||
|
|
||||||
match ty::get(function_type).sty {
|
match ty::get(function_type).sty {
|
||||||
ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
|
store: ty::RegionTraitStore(..),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
freevars::with_freevars(tcx, expr.id, |freevars| {
|
freevars::with_freevars(tcx, expr.id, |freevars| {
|
||||||
propagate_upupvar_borrow_kind(rcx, expr, freevars);
|
propagate_upupvar_borrow_kind(rcx, expr, freevars);
|
||||||
})
|
})
|
||||||
|
|
|
@ -532,7 +532,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||||
let resolve_object_cast = |src: &ast::Expr, target_ty: ty::t| {
|
let resolve_object_cast = |src: &ast::Expr, target_ty: ty::t| {
|
||||||
match ty::get(target_ty).sty {
|
match ty::get(target_ty).sty {
|
||||||
// Bounds of type's contents are not checked here, but in kind.rs.
|
// Bounds of type's contents are not checked here, but in kind.rs.
|
||||||
ty::ty_trait(~ty::TyTrait {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
def_id: target_def_id, substs: ref target_substs, store, ..
|
def_id: target_def_id, substs: ref target_substs, store, ..
|
||||||
}) => {
|
}) => {
|
||||||
fn mutability_allowed(a_mutbl: ast::Mutability,
|
fn mutability_allowed(a_mutbl: ast::Mutability,
|
||||||
|
@ -543,7 +543,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||||
// Look up vtables for the type we're casting to,
|
// Look up vtables for the type we're casting to,
|
||||||
// passing in the source and target type. The source
|
// passing in the source and target type. The source
|
||||||
// must be a pointer type suitable to the object sigil,
|
// must be a pointer type suitable to the object sigil,
|
||||||
// e.g.: `&x as &Trait` or `~x as ~Trait`
|
// e.g.: `&x as &Trait` or `box x as Box<Trait>`
|
||||||
let ty = structurally_resolved_type(fcx, ex.span,
|
let ty = structurally_resolved_type(fcx, ex.span,
|
||||||
fcx.expr_ty(src));
|
fcx.expr_ty(src));
|
||||||
match (&ty::get(ty).sty, store) {
|
match (&ty::get(ty).sty, store) {
|
||||||
|
@ -606,8 +606,8 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||||
(_, ty::UniqTraitStore) => {
|
(_, ty::UniqTraitStore) => {
|
||||||
fcx.ccx.tcx.sess.span_err(
|
fcx.ccx.tcx.sess.span_err(
|
||||||
ex.span,
|
ex.span,
|
||||||
format!("can only cast an ~-pointer \
|
format!("can only cast an boxed pointer \
|
||||||
to a ~-object, not a {}",
|
to a boxed object, not a {}",
|
||||||
ty::ty_sort_str(fcx.tcx(), ty)));
|
ty::ty_sort_str(fcx.tcx(), ty)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ fn type_is_defined_in_local_crate(original_type: t) -> bool {
|
||||||
ty::walk_ty(original_type, |t| {
|
ty::walk_ty(original_type, |t| {
|
||||||
match get(t).sty {
|
match get(t).sty {
|
||||||
ty_enum(def_id, _) |
|
ty_enum(def_id, _) |
|
||||||
ty_trait(~ty::TyTrait { def_id, .. }) |
|
ty_trait(box ty::TyTrait { def_id, .. }) |
|
||||||
ty_struct(def_id, _) => {
|
ty_struct(def_id, _) => {
|
||||||
if def_id.krate == ast::LOCAL_CRATE {
|
if def_id.krate == ast::LOCAL_CRATE {
|
||||||
found_nominal = true;
|
found_nominal = true;
|
||||||
|
@ -129,7 +129,7 @@ fn get_base_type_def_id(inference_context: &InferCtxt,
|
||||||
match get(base_type).sty {
|
match get(base_type).sty {
|
||||||
ty_enum(def_id, _) |
|
ty_enum(def_id, _) |
|
||||||
ty_struct(def_id, _) |
|
ty_struct(def_id, _) |
|
||||||
ty_trait(~ty::TyTrait { def_id, .. }) => {
|
ty_trait(box ty::TyTrait { def_id, .. }) => {
|
||||||
return Some(def_id);
|
return Some(def_id);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -121,7 +121,10 @@ impl<'f> Coerce<'f> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
|
store: ty::RegionTraitStore(..),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
return self.unpack_actual_value(a, |sty_a| {
|
return self.unpack_actual_value(a, |sty_a| {
|
||||||
self.coerce_borrowed_fn(a, sty_a, b)
|
self.coerce_borrowed_fn(a, sty_a, b)
|
||||||
});
|
});
|
||||||
|
@ -133,7 +136,7 @@ impl<'f> Coerce<'f> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_trait(~ty::TyTrait {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
def_id, ref substs, store: ty::UniqTraitStore, bounds
|
def_id, ref substs, store: ty::UniqTraitStore, bounds
|
||||||
}) => {
|
}) => {
|
||||||
let result = self.unpack_actual_value(a, |sty_a| {
|
let result = self.unpack_actual_value(a, |sty_a| {
|
||||||
|
@ -152,7 +155,7 @@ impl<'f> Coerce<'f> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_trait(~ty::TyTrait {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
def_id, ref substs, store: ty::RegionTraitStore(region, m), bounds
|
def_id, ref substs, store: ty::RegionTraitStore(region, m), bounds
|
||||||
}) => {
|
}) => {
|
||||||
let result = self.unpack_actual_value(a, |sty_a| {
|
let result = self.unpack_actual_value(a, |sty_a| {
|
||||||
|
@ -332,7 +335,12 @@ impl<'f> Coerce<'f> {
|
||||||
let r_a = self.get_ref().infcx.next_region_var(coercion);
|
let r_a = self.get_ref().infcx.next_region_var(coercion);
|
||||||
|
|
||||||
let a_borrowed = match *sty_a {
|
let a_borrowed = match *sty_a {
|
||||||
ty::ty_trait(~ty::TyTrait { def_id, ref substs, bounds, .. }) => {
|
ty::ty_trait(box ty::TyTrait {
|
||||||
|
def_id,
|
||||||
|
ref substs,
|
||||||
|
bounds,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
ty::mk_trait(tcx, def_id, substs.clone(),
|
ty::mk_trait(tcx, def_id, substs.clone(),
|
||||||
ty::RegionTraitStore(r_a, b_mutbl), bounds)
|
ty::RegionTraitStore(r_a, b_mutbl), bounds)
|
||||||
}
|
}
|
||||||
|
|
|
@ -683,7 +683,7 @@ impl<'a> InferCtxt<'a> {
|
||||||
ty::EmptyBuiltinBounds());
|
ty::EmptyBuiltinBounds());
|
||||||
let dummy1 = self.resolve_type_vars_if_possible(dummy0);
|
let dummy1 = self.resolve_type_vars_if_possible(dummy0);
|
||||||
match ty::get(dummy1).sty {
|
match ty::get(dummy1).sty {
|
||||||
ty::ty_trait(~ty::TyTrait { ref def_id, ref substs, .. }) => {
|
ty::ty_trait(box ty::TyTrait { ref def_id, ref substs, .. }) => {
|
||||||
ty::TraitRef {
|
ty::TraitRef {
|
||||||
def_id: *def_id,
|
def_id: *def_id,
|
||||||
substs: (*substs).clone(),
|
substs: (*substs).clone(),
|
||||||
|
|
|
@ -190,7 +190,7 @@ going on:
|
||||||
*p += 1; *p
|
*p += 1; *p
|
||||||
}
|
}
|
||||||
fn weird() {
|
fn weird() {
|
||||||
let mut x: ~Foo = ~Foo { ... };
|
let mut x: Box<Foo> = box Foo { ... };
|
||||||
'a: add(&mut (*x).f,
|
'a: add(&mut (*x).f,
|
||||||
'b: inc(&mut (*x).f)) // (..)
|
'b: inc(&mut (*x).f)) // (..)
|
||||||
}
|
}
|
||||||
|
@ -243,11 +243,11 @@ this similar but unsound example:
|
||||||
*p += v;
|
*p += v;
|
||||||
}
|
}
|
||||||
...
|
...
|
||||||
fn consume(x: ~Foo) -> uint {
|
fn consume(x: Box<Foo>) -> uint {
|
||||||
x.f + x.g
|
x.f + x.g
|
||||||
}
|
}
|
||||||
fn weird() {
|
fn weird() {
|
||||||
let mut x: ~Foo = ~Foo { ... };
|
let mut x: Box<Foo> = box Foo { ... };
|
||||||
'a: add(&mut (*x).f, consume(x)) // (..)
|
'a: add(&mut (*x).f, consume(x)) // (..)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -741,7 +741,7 @@ impl<'a> ConstraintContext<'a> {
|
||||||
substs, variance);
|
substs, variance);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_trait(~ty::TyTrait { def_id, ref substs, .. }) => {
|
ty::ty_trait(box ty::TyTrait { def_id, ref substs, .. }) => {
|
||||||
let trait_def = ty::lookup_trait_def(self.tcx(), def_id);
|
let trait_def = ty::lookup_trait_def(self.tcx(), def_id);
|
||||||
self.add_constraints_from_substs(def_id, &trait_def.generics,
|
self.add_constraints_from_substs(def_id, &trait_def.generics,
|
||||||
substs, variance);
|
substs, variance);
|
||||||
|
@ -768,11 +768,15 @@ impl<'a> ConstraintContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_bare_fn(ty::BareFnTy { ref sig, .. }) |
|
ty::ty_bare_fn(ty::BareFnTy { ref sig, .. }) |
|
||||||
ty::ty_closure(~ty::ClosureTy { ref sig, store: ty::UniqTraitStore, .. }) => {
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
|
ref sig,
|
||||||
|
store: ty::UniqTraitStore,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
self.add_constraints_from_sig(sig, variance);
|
self.add_constraints_from_sig(sig, variance);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_closure(~ty::ClosureTy { ref sig,
|
ty::ty_closure(box ty::ClosureTy { ref sig,
|
||||||
store: ty::RegionTraitStore(region, _), .. }) => {
|
store: ty::RegionTraitStore(region, _), .. }) => {
|
||||||
let contra = self.contravariant(variance);
|
let contra = self.contravariant(variance);
|
||||||
self.add_constraints_from_region(region, contra);
|
self.add_constraints_from_region(region, contra);
|
||||||
|
|
|
@ -203,7 +203,7 @@ pub fn mt_to_str(cx: &ctxt, m: &mt) -> ~str {
|
||||||
|
|
||||||
pub fn trait_store_to_str(cx: &ctxt, s: ty::TraitStore) -> ~str {
|
pub fn trait_store_to_str(cx: &ctxt, s: ty::TraitStore) -> ~str {
|
||||||
match s {
|
match s {
|
||||||
ty::UniqTraitStore => "~".to_owned(),
|
ty::UniqTraitStore => "Box ".to_owned(),
|
||||||
ty::RegionTraitStore(r, m) => {
|
ty::RegionTraitStore(r, m) => {
|
||||||
format!("{}{}", region_ptr_to_str(cx, r), mutability_to_str(m))
|
format!("{}{}", region_ptr_to_str(cx, r), mutability_to_str(m))
|
||||||
}
|
}
|
||||||
|
@ -385,7 +385,7 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> ~str {
|
||||||
did,
|
did,
|
||||||
false)
|
false)
|
||||||
}
|
}
|
||||||
ty_trait(~ty::TyTrait {
|
ty_trait(box ty::TyTrait {
|
||||||
def_id: did, ref substs, store, ref bounds
|
def_id: did, ref substs, store, ref bounds
|
||||||
}) => {
|
}) => {
|
||||||
let base = ty::item_path_str(cx, did);
|
let base = ty::item_path_str(cx, did);
|
||||||
|
@ -500,7 +500,7 @@ impl<T:Repr> Repr for @T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T:Repr> Repr for ~T {
|
impl<T:Repr> Repr for Box<T> {
|
||||||
fn repr(&self, tcx: &ctxt) -> ~str {
|
fn repr(&self, tcx: &ctxt) -> ~str {
|
||||||
(&**self).repr(tcx)
|
(&**self).repr(tcx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -684,26 +684,26 @@ pub enum Type {
|
||||||
Self(ast::NodeId),
|
Self(ast::NodeId),
|
||||||
/// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
|
/// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
|
||||||
Primitive(ast::PrimTy),
|
Primitive(ast::PrimTy),
|
||||||
Closure(~ClosureDecl, Option<Lifetime>),
|
Closure(Box<ClosureDecl>, Option<Lifetime>),
|
||||||
Proc(~ClosureDecl),
|
Proc(Box<ClosureDecl>),
|
||||||
/// extern "ABI" fn
|
/// extern "ABI" fn
|
||||||
BareFunction(~BareFunctionDecl),
|
BareFunction(Box<BareFunctionDecl>),
|
||||||
Tuple(Vec<Type>),
|
Tuple(Vec<Type>),
|
||||||
Vector(~Type),
|
Vector(Box<Type>),
|
||||||
FixedVector(~Type, ~str),
|
FixedVector(Box<Type>, ~str),
|
||||||
String,
|
String,
|
||||||
Bool,
|
Bool,
|
||||||
/// aka TyNil
|
/// aka TyNil
|
||||||
Unit,
|
Unit,
|
||||||
/// aka TyBot
|
/// aka TyBot
|
||||||
Bottom,
|
Bottom,
|
||||||
Unique(~Type),
|
Unique(Box<Type>),
|
||||||
Managed(~Type),
|
Managed(Box<Type>),
|
||||||
RawPointer(Mutability, ~Type),
|
RawPointer(Mutability, Box<Type>),
|
||||||
BorrowedRef {
|
BorrowedRef {
|
||||||
pub lifetime: Option<Lifetime>,
|
pub lifetime: Option<Lifetime>,
|
||||||
pub mutability: Mutability,
|
pub mutability: Mutability,
|
||||||
pub type_: ~Type,
|
pub type_: Box<Type>,
|
||||||
},
|
},
|
||||||
// region, raw, other boxes, mutable
|
// region, raw, other boxes, mutable
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,8 +83,8 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, class: Option<&
|
||||||
let klass = match next.tok {
|
let klass = match next.tok {
|
||||||
// If this '&' token is directly adjacent to another token, assume
|
// If this '&' token is directly adjacent to another token, assume
|
||||||
// that it's the address-of operator instead of the and-operator.
|
// that it's the address-of operator instead of the and-operator.
|
||||||
// This allows us to give all pointers their own class (~ and @ are
|
// This allows us to give all pointers their own class (`Box` and
|
||||||
// below).
|
// `@` are below).
|
||||||
t::BINOP(t::AND) if lexer.peek().sp.lo == next.sp.hi => "kw-2",
|
t::BINOP(t::AND) if lexer.peek().sp.lo == next.sp.hi => "kw-2",
|
||||||
t::AT | t::TILDE => "kw-2",
|
t::AT | t::TILDE => "kw-2",
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,11 @@ use html::markdown;
|
||||||
use passes;
|
use passes;
|
||||||
use visit_ast::RustdocVisitor;
|
use visit_ast::RustdocVisitor;
|
||||||
|
|
||||||
pub fn run(input: &str, cfgs: Vec<~str>,
|
pub fn run(input: &str,
|
||||||
libs: HashSet<Path>, mut test_args: Vec<~str>) -> int {
|
cfgs: Vec<~str>,
|
||||||
|
libs: HashSet<Path>,
|
||||||
|
mut test_args: Vec<~str>)
|
||||||
|
-> int {
|
||||||
let input_path = Path::new(input);
|
let input_path = Path::new(input);
|
||||||
let input = driver::FileInput(input_path.clone());
|
let input = driver::FileInput(input_path.clone());
|
||||||
|
|
||||||
|
@ -126,7 +129,7 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
|
||||||
let old = io::stdio::set_stderr(box w1);
|
let old = io::stdio::set_stderr(box w1);
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
let mut p = io::ChanReader::new(rx);
|
let mut p = io::ChanReader::new(rx);
|
||||||
let mut err = old.unwrap_or(box io::stderr() as ~Writer:Send);
|
let mut err = old.unwrap_or(box io::stderr() as Box<Writer:Send>);
|
||||||
io::util::copy(&mut p, &mut err).unwrap();
|
io::util::copy(&mut p, &mut err).unwrap();
|
||||||
});
|
});
|
||||||
let emitter = diagnostic::EmitterWriter::new(box w2);
|
let emitter = diagnostic::EmitterWriter::new(box w2);
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
/// (the uv event loop).
|
/// (the uv event loop).
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::sync::arc::UnsafeArc;
|
|
||||||
use std::rt::task::{BlockedTask, Task};
|
|
||||||
use std::rt::local::Local;
|
use std::rt::local::Local;
|
||||||
|
use std::rt::task::{BlockedTask, Task};
|
||||||
|
use std::sync::arc::UnsafeArc;
|
||||||
|
|
||||||
use homing::HomingMissile;
|
use homing::HomingMissile;
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ impl Access {
|
||||||
let inner: &mut Inner = unsafe { cast::transmute(self.inner.get()) };
|
let inner: &mut Inner = unsafe { cast::transmute(self.inner.get()) };
|
||||||
|
|
||||||
if inner.held {
|
if inner.held {
|
||||||
let t: ~Task = Local::take();
|
let t: Box<Task> = Local::take();
|
||||||
t.deschedule(1, |task| {
|
t.deschedule(1, |task| {
|
||||||
inner.queue.push(task);
|
inner.queue.push(task);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -26,12 +26,12 @@ pub struct AsyncWatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Payload {
|
struct Payload {
|
||||||
callback: ~Callback:Send,
|
callback: Box<Callback:Send>,
|
||||||
exit_flag: Exclusive<bool>,
|
exit_flag: Exclusive<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsyncWatcher {
|
impl AsyncWatcher {
|
||||||
pub fn new(loop_: &mut Loop, cb: ~Callback:Send) -> AsyncWatcher {
|
pub fn new(loop_: &mut Loop, cb: Box<Callback:Send>) -> AsyncWatcher {
|
||||||
let handle = UvHandle::alloc(None::<AsyncWatcher>, uvll::UV_ASYNC);
|
let handle = UvHandle::alloc(None::<AsyncWatcher>, uvll::UV_ASYNC);
|
||||||
assert_eq!(unsafe {
|
assert_eq!(unsafe {
|
||||||
uvll::uv_async_init(loop_.handle, handle, async_cb)
|
uvll::uv_async_init(loop_.handle, handle, async_cb)
|
||||||
|
@ -93,7 +93,7 @@ extern fn async_cb(handle: *uvll::uv_async_t) {
|
||||||
|
|
||||||
extern fn close_cb(handle: *uvll::uv_handle_t) {
|
extern fn close_cb(handle: *uvll::uv_handle_t) {
|
||||||
// drop the payload
|
// drop the payload
|
||||||
let _payload: ~Payload = unsafe {
|
let _payload: Box<Payload> = unsafe {
|
||||||
cast::transmute(uvll::get_data_for_uv_handle(handle))
|
cast::transmute(uvll::get_data_for_uv_handle(handle))
|
||||||
};
|
};
|
||||||
// and then free the handle
|
// and then free the handle
|
||||||
|
|
|
@ -100,7 +100,7 @@ pub trait HomingIO {
|
||||||
// to go (remember we have no preemption, so we're guaranteed to stay on
|
// to go (remember we have no preemption, so we're guaranteed to stay on
|
||||||
// this event loop as long as we avoid the scheduler).
|
// this event loop as long as we avoid the scheduler).
|
||||||
if cur_loop_id != destination {
|
if cur_loop_id != destination {
|
||||||
let cur_task: ~Task = Local::take();
|
let cur_task: Box<Task> = Local::take();
|
||||||
cur_task.deschedule(1, |task| {
|
cur_task.deschedule(1, |task| {
|
||||||
self.home().send(task);
|
self.home().send(task);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -19,11 +19,11 @@ pub struct IdleWatcher {
|
||||||
handle: *uvll::uv_idle_t,
|
handle: *uvll::uv_idle_t,
|
||||||
idle_flag: bool,
|
idle_flag: bool,
|
||||||
closed: bool,
|
closed: bool,
|
||||||
callback: ~Callback:Send,
|
callback: Box<Callback:Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IdleWatcher {
|
impl IdleWatcher {
|
||||||
pub fn new(loop_: &mut Loop, cb: ~Callback:Send) -> ~IdleWatcher {
|
pub fn new(loop_: &mut Loop, cb: Box<Callback:Send>) -> Box<IdleWatcher> {
|
||||||
let handle = UvHandle::alloc(None::<IdleWatcher>, uvll::UV_IDLE);
|
let handle = UvHandle::alloc(None::<IdleWatcher>, uvll::UV_IDLE);
|
||||||
assert_eq!(unsafe {
|
assert_eq!(unsafe {
|
||||||
uvll::uv_idle_init(loop_.handle, handle)
|
uvll::uv_idle_init(loop_.handle, handle)
|
||||||
|
@ -49,7 +49,7 @@ impl IdleWatcher {
|
||||||
extern fn onetime_cb(handle: *uvll::uv_idle_t) {
|
extern fn onetime_cb(handle: *uvll::uv_idle_t) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = uvll::get_data_for_uv_handle(handle);
|
let data = uvll::get_data_for_uv_handle(handle);
|
||||||
let f: ~proc() = cast::transmute(data);
|
let f: Box<proc()> = cast::transmute(data);
|
||||||
(*f)();
|
(*f)();
|
||||||
assert_eq!(uvll::uv_idle_stop(handle), 0);
|
assert_eq!(uvll::uv_idle_stop(handle), 0);
|
||||||
uvll::uv_close(handle, close_cb);
|
uvll::uv_close(handle, close_cb);
|
||||||
|
@ -126,16 +126,16 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk(v: uint) -> (~IdleWatcher, Chan) {
|
fn mk(v: uint) -> (Box<IdleWatcher>, Chan) {
|
||||||
let rc = Rc::new(RefCell::new((None, 0)));
|
let rc = Rc::new(RefCell::new((None, 0)));
|
||||||
let cb = box MyCallback(rc.clone(), v);
|
let cb = box MyCallback(rc.clone(), v);
|
||||||
let cb = cb as ~Callback:;
|
let cb = cb as Box<Callback:>;
|
||||||
let cb = unsafe { cast::transmute(cb) };
|
let cb = unsafe { cast::transmute(cb) };
|
||||||
(IdleWatcher::new(&mut local_loop().loop_, cb), rc)
|
(IdleWatcher::new(&mut local_loop().loop_, cb), rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sleep(chan: &Chan) -> uint {
|
fn sleep(chan: &Chan) -> uint {
|
||||||
let task: ~Task = Local::take();
|
let task: Box<Task> = Local::take();
|
||||||
task.deschedule(1, |task| {
|
task.deschedule(1, |task| {
|
||||||
match *chan.borrow_mut().deref_mut() {
|
match *chan.borrow_mut().deref_mut() {
|
||||||
(ref mut slot, _) => {
|
(ref mut slot, _) => {
|
||||||
|
|
|
@ -47,11 +47,11 @@ via `close` and `delete` methods.
|
||||||
#[cfg(test)] extern crate realrustuv = "rustuv";
|
#[cfg(test)] extern crate realrustuv = "rustuv";
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
|
use libc::{c_int, c_void};
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::IoError;
|
use std::io::IoError;
|
||||||
use std::io;
|
use std::io;
|
||||||
use libc::{c_int, c_void};
|
|
||||||
use std::ptr::null;
|
use std::ptr::null;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rt::local::Local;
|
use std::rt::local::Local;
|
||||||
|
@ -124,8 +124,8 @@ pub mod stream;
|
||||||
/// // this code is running inside of a green task powered by libuv
|
/// // this code is running inside of a green task powered by libuv
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn event_loop() -> ~rtio::EventLoop:Send {
|
pub fn event_loop() -> Box<rtio::EventLoop:Send> {
|
||||||
box uvio::UvEventLoop::new() as ~rtio::EventLoop:Send
|
box uvio::UvEventLoop::new() as Box<rtio::EventLoop:Send>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that wraps a uv handle
|
/// A type that wraps a uv handle
|
||||||
|
@ -149,9 +149,9 @@ pub trait UvHandle<T> {
|
||||||
cast::transmute(uvll::get_data_for_uv_handle(*h))
|
cast::transmute(uvll::get_data_for_uv_handle(*h))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn install(~self) -> ~Self {
|
fn install(~self) -> Box<Self> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let myptr = cast::transmute::<&~Self, &*u8>(&self);
|
let myptr = cast::transmute::<&Box<Self>, &*u8>(&self);
|
||||||
uvll::set_data_for_uv_handle(self.uv_handle(), *myptr);
|
uvll::set_data_for_uv_handle(self.uv_handle(), *myptr);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
|
@ -242,7 +242,7 @@ fn wait_until_woken_after(slot: *mut Option<BlockedTask>,
|
||||||
let _f = ForbidUnwind::new("wait_until_woken_after");
|
let _f = ForbidUnwind::new("wait_until_woken_after");
|
||||||
unsafe {
|
unsafe {
|
||||||
assert!((*slot).is_none());
|
assert!((*slot).is_none());
|
||||||
let task: ~Task = Local::take();
|
let task: Box<Task> = Local::take();
|
||||||
loop_.modify_blockers(1);
|
loop_.modify_blockers(1);
|
||||||
task.deschedule(1, |task| {
|
task.deschedule(1, |task| {
|
||||||
*slot = Some(task);
|
*slot = Some(task);
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use libc::{size_t, ssize_t, c_int, c_void, c_uint};
|
||||||
|
use libc;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::io::{IoError, IoResult};
|
use std::io::{IoError, IoResult};
|
||||||
use std::io::net::ip;
|
use std::io::net::ip;
|
||||||
use libc::{size_t, ssize_t, c_int, c_void, c_uint};
|
|
||||||
use libc;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rt::rtio;
|
use std::rt::rtio;
|
||||||
|
@ -152,7 +152,7 @@ fn socket_name(sk: SocketNameKind,
|
||||||
pub struct ConnectCtx {
|
pub struct ConnectCtx {
|
||||||
pub status: c_int,
|
pub status: c_int,
|
||||||
pub task: Option<BlockedTask>,
|
pub task: Option<BlockedTask>,
|
||||||
pub timer: Option<~TimerWatcher>,
|
pub timer: Option<Box<TimerWatcher>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AcceptTimeout {
|
pub struct AcceptTimeout {
|
||||||
|
@ -352,12 +352,12 @@ pub struct TcpListener {
|
||||||
home: HomeHandle,
|
home: HomeHandle,
|
||||||
handle: *uvll::uv_pipe_t,
|
handle: *uvll::uv_pipe_t,
|
||||||
closing_task: Option<BlockedTask>,
|
closing_task: Option<BlockedTask>,
|
||||||
outgoing: Sender<Result<~rtio::RtioTcpStream:Send, IoError>>,
|
outgoing: Sender<Result<Box<rtio::RtioTcpStream:Send>, IoError>>,
|
||||||
incoming: Receiver<Result<~rtio::RtioTcpStream:Send, IoError>>,
|
incoming: Receiver<Result<Box<rtio::RtioTcpStream:Send>, IoError>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TcpAcceptor {
|
pub struct TcpAcceptor {
|
||||||
listener: ~TcpListener,
|
listener: Box<TcpListener>,
|
||||||
timeout: AcceptTimeout,
|
timeout: AcceptTimeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,7 +455,7 @@ impl rtio::RtioTcpStream for TcpWatcher {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone(&self) -> ~rtio::RtioTcpStream:Send {
|
fn clone(&self) -> Box<rtio::RtioTcpStream:Send> {
|
||||||
box TcpWatcher {
|
box TcpWatcher {
|
||||||
handle: self.handle,
|
handle: self.handle,
|
||||||
stream: StreamWatcher::new(self.handle),
|
stream: StreamWatcher::new(self.handle),
|
||||||
|
@ -463,7 +463,7 @@ impl rtio::RtioTcpStream for TcpWatcher {
|
||||||
refcount: self.refcount.clone(),
|
refcount: self.refcount.clone(),
|
||||||
write_access: self.write_access.clone(),
|
write_access: self.write_access.clone(),
|
||||||
read_access: self.read_access.clone(),
|
read_access: self.read_access.clone(),
|
||||||
} as ~rtio::RtioTcpStream:Send
|
} as Box<rtio::RtioTcpStream:Send>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_write(&mut self) -> Result<(), IoError> {
|
fn close_write(&mut self) -> Result<(), IoError> {
|
||||||
|
@ -516,7 +516,7 @@ impl Drop for TcpWatcher {
|
||||||
|
|
||||||
impl TcpListener {
|
impl TcpListener {
|
||||||
pub fn bind(io: &mut UvIoFactory, address: ip::SocketAddr)
|
pub fn bind(io: &mut UvIoFactory, address: ip::SocketAddr)
|
||||||
-> Result<~TcpListener, UvError> {
|
-> Result<Box<TcpListener>, UvError> {
|
||||||
let handle = unsafe { uvll::malloc_handle(uvll::UV_TCP) };
|
let handle = unsafe { uvll::malloc_handle(uvll::UV_TCP) };
|
||||||
assert_eq!(unsafe {
|
assert_eq!(unsafe {
|
||||||
uvll::uv_tcp_init(io.uv_loop(), handle)
|
uvll::uv_tcp_init(io.uv_loop(), handle)
|
||||||
|
@ -557,7 +557,7 @@ impl rtio::RtioSocket for TcpListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rtio::RtioTcpListener for TcpListener {
|
impl rtio::RtioTcpListener for TcpListener {
|
||||||
fn listen(~self) -> Result<~rtio::RtioTcpAcceptor:Send, IoError> {
|
fn listen(~self) -> Result<Box<rtio::RtioTcpAcceptor:Send>, IoError> {
|
||||||
// create the acceptor object from ourselves
|
// create the acceptor object from ourselves
|
||||||
let mut acceptor = box TcpAcceptor {
|
let mut acceptor = box TcpAcceptor {
|
||||||
listener: self,
|
listener: self,
|
||||||
|
@ -567,7 +567,7 @@ impl rtio::RtioTcpListener for TcpListener {
|
||||||
let _m = acceptor.fire_homing_missile();
|
let _m = acceptor.fire_homing_missile();
|
||||||
// FIXME: the 128 backlog should be configurable
|
// FIXME: the 128 backlog should be configurable
|
||||||
match unsafe { uvll::uv_listen(acceptor.listener.handle, 128, listen_cb) } {
|
match unsafe { uvll::uv_listen(acceptor.listener.handle, 128, listen_cb) } {
|
||||||
0 => Ok(acceptor as ~rtio::RtioTcpAcceptor:Send),
|
0 => Ok(acceptor as Box<rtio::RtioTcpAcceptor:Send>),
|
||||||
n => Err(uv_error_to_io_error(UvError(n))),
|
n => Err(uv_error_to_io_error(UvError(n))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -583,7 +583,7 @@ extern fn listen_cb(server: *uvll::uv_stream_t, status: c_int) {
|
||||||
});
|
});
|
||||||
let client = TcpWatcher::new_home(&loop_, tcp.home().clone());
|
let client = TcpWatcher::new_home(&loop_, tcp.home().clone());
|
||||||
assert_eq!(unsafe { uvll::uv_accept(server, client.handle) }, 0);
|
assert_eq!(unsafe { uvll::uv_accept(server, client.handle) }, 0);
|
||||||
Ok(box client as ~rtio::RtioTcpStream:Send)
|
Ok(box client as Box<rtio::RtioTcpStream:Send>)
|
||||||
}
|
}
|
||||||
n => Err(uv_error_to_io_error(UvError(n)))
|
n => Err(uv_error_to_io_error(UvError(n)))
|
||||||
};
|
};
|
||||||
|
@ -611,7 +611,7 @@ impl rtio::RtioSocket for TcpAcceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rtio::RtioTcpAcceptor for TcpAcceptor {
|
impl rtio::RtioTcpAcceptor for TcpAcceptor {
|
||||||
fn accept(&mut self) -> Result<~rtio::RtioTcpStream:Send, IoError> {
|
fn accept(&mut self) -> Result<Box<rtio::RtioTcpStream:Send>, IoError> {
|
||||||
self.timeout.accept(&self.listener.incoming)
|
self.timeout.accept(&self.listener.incoming)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,14 +879,14 @@ impl rtio::RtioUdpSocket for UdpWatcher {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone(&self) -> ~rtio::RtioUdpSocket:Send {
|
fn clone(&self) -> Box<rtio::RtioUdpSocket:Send> {
|
||||||
box UdpWatcher {
|
box UdpWatcher {
|
||||||
handle: self.handle,
|
handle: self.handle,
|
||||||
home: self.home.clone(),
|
home: self.home.clone(),
|
||||||
refcount: self.refcount.clone(),
|
refcount: self.refcount.clone(),
|
||||||
write_access: self.write_access.clone(),
|
write_access: self.write_access.clone(),
|
||||||
read_access: self.read_access.clone(),
|
read_access: self.read_access.clone(),
|
||||||
} as ~rtio::RtioUdpSocket:Send
|
} as Box<rtio::RtioUdpSocket:Send>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use libc;
|
||||||
use std::c_str::CString;
|
use std::c_str::CString;
|
||||||
use std::io::IoError;
|
use std::io::IoError;
|
||||||
use libc;
|
|
||||||
use std::rt::rtio::{RtioPipe, RtioUnixListener, RtioUnixAcceptor};
|
use std::rt::rtio::{RtioPipe, RtioUnixListener, RtioUnixAcceptor};
|
||||||
|
|
||||||
use access::Access;
|
use access::Access;
|
||||||
|
@ -36,12 +36,12 @@ pub struct PipeWatcher {
|
||||||
pub struct PipeListener {
|
pub struct PipeListener {
|
||||||
home: HomeHandle,
|
home: HomeHandle,
|
||||||
pipe: *uvll::uv_pipe_t,
|
pipe: *uvll::uv_pipe_t,
|
||||||
outgoing: Sender<Result<~RtioPipe:Send, IoError>>,
|
outgoing: Sender<Result<Box<RtioPipe:Send>, IoError>>,
|
||||||
incoming: Receiver<Result<~RtioPipe:Send, IoError>>,
|
incoming: Receiver<Result<Box<RtioPipe:Send>, IoError>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PipeAcceptor {
|
pub struct PipeAcceptor {
|
||||||
listener: ~PipeListener,
|
listener: Box<PipeListener>,
|
||||||
timeout: net::AcceptTimeout,
|
timeout: net::AcceptTimeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ impl RtioPipe for PipeWatcher {
|
||||||
self.stream.write(buf).map_err(uv_error_to_io_error)
|
self.stream.write(buf).map_err(uv_error_to_io_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone(&self) -> ~RtioPipe:Send {
|
fn clone(&self) -> Box<RtioPipe:Send> {
|
||||||
box PipeWatcher {
|
box PipeWatcher {
|
||||||
stream: StreamWatcher::new(self.stream.handle),
|
stream: StreamWatcher::new(self.stream.handle),
|
||||||
defused: false,
|
defused: false,
|
||||||
|
@ -129,7 +129,7 @@ impl RtioPipe for PipeWatcher {
|
||||||
refcount: self.refcount.clone(),
|
refcount: self.refcount.clone(),
|
||||||
read_access: self.read_access.clone(),
|
read_access: self.read_access.clone(),
|
||||||
write_access: self.write_access.clone(),
|
write_access: self.write_access.clone(),
|
||||||
} as ~RtioPipe:Send
|
} as Box<RtioPipe:Send>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ impl Drop for PipeWatcher {
|
||||||
|
|
||||||
impl PipeListener {
|
impl PipeListener {
|
||||||
pub fn bind(io: &mut UvIoFactory, name: &CString)
|
pub fn bind(io: &mut UvIoFactory, name: &CString)
|
||||||
-> Result<~PipeListener, UvError>
|
-> Result<Box<PipeListener>, UvError>
|
||||||
{
|
{
|
||||||
let pipe = PipeWatcher::new(io, false);
|
let pipe = PipeWatcher::new(io, false);
|
||||||
match unsafe {
|
match unsafe {
|
||||||
|
@ -179,7 +179,7 @@ impl PipeListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RtioUnixListener for PipeListener {
|
impl RtioUnixListener for PipeListener {
|
||||||
fn listen(~self) -> Result<~RtioUnixAcceptor:Send, IoError> {
|
fn listen(~self) -> Result<Box<RtioUnixAcceptor:Send>, IoError> {
|
||||||
// create the acceptor object from ourselves
|
// create the acceptor object from ourselves
|
||||||
let mut acceptor = box PipeAcceptor {
|
let mut acceptor = box PipeAcceptor {
|
||||||
listener: self,
|
listener: self,
|
||||||
|
@ -189,7 +189,7 @@ impl RtioUnixListener for PipeListener {
|
||||||
let _m = acceptor.fire_homing_missile();
|
let _m = acceptor.fire_homing_missile();
|
||||||
// FIXME: the 128 backlog should be configurable
|
// FIXME: the 128 backlog should be configurable
|
||||||
match unsafe { uvll::uv_listen(acceptor.listener.pipe, 128, listen_cb) } {
|
match unsafe { uvll::uv_listen(acceptor.listener.pipe, 128, listen_cb) } {
|
||||||
0 => Ok(acceptor as ~RtioUnixAcceptor:Send),
|
0 => Ok(acceptor as Box<RtioUnixAcceptor:Send>),
|
||||||
n => Err(uv_error_to_io_error(UvError(n))),
|
n => Err(uv_error_to_io_error(UvError(n))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ extern fn listen_cb(server: *uvll::uv_stream_t, status: libc::c_int) {
|
||||||
});
|
});
|
||||||
let client = PipeWatcher::new_home(&loop_, pipe.home().clone(), false);
|
let client = PipeWatcher::new_home(&loop_, pipe.home().clone(), false);
|
||||||
assert_eq!(unsafe { uvll::uv_accept(server, client.handle()) }, 0);
|
assert_eq!(unsafe { uvll::uv_accept(server, client.handle()) }, 0);
|
||||||
Ok(box client as ~RtioPipe:Send)
|
Ok(box client as Box<RtioPipe:Send>)
|
||||||
}
|
}
|
||||||
n => Err(uv_error_to_io_error(UvError(n)))
|
n => Err(uv_error_to_io_error(UvError(n)))
|
||||||
};
|
};
|
||||||
|
@ -231,7 +231,7 @@ impl Drop for PipeListener {
|
||||||
// PipeAcceptor implementation and traits
|
// PipeAcceptor implementation and traits
|
||||||
|
|
||||||
impl RtioUnixAcceptor for PipeAcceptor {
|
impl RtioUnixAcceptor for PipeAcceptor {
|
||||||
fn accept(&mut self) -> Result<~RtioPipe:Send, IoError> {
|
fn accept(&mut self) -> Result<Box<RtioPipe:Send>, IoError> {
|
||||||
self.timeout.accept(&self.listener.incoming)
|
self.timeout.accept(&self.listener.incoming)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::io::IoError;
|
|
||||||
use std::io::process;
|
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
use libc;
|
use libc;
|
||||||
|
use std::io::IoError;
|
||||||
|
use std::io::process;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rt::rtio::RtioProcess;
|
use std::rt::rtio::RtioProcess;
|
||||||
use std::rt::task::BlockedTask;
|
use std::rt::task::BlockedTask;
|
||||||
|
@ -40,8 +40,7 @@ impl Process {
|
||||||
/// Returns either the corresponding process object or an error which
|
/// Returns either the corresponding process object or an error which
|
||||||
/// occurred.
|
/// occurred.
|
||||||
pub fn spawn(io_loop: &mut UvIoFactory, config: process::ProcessConfig)
|
pub fn spawn(io_loop: &mut UvIoFactory, config: process::ProcessConfig)
|
||||||
-> Result<(~Process, ~[Option<PipeWatcher>]), UvError>
|
-> Result<(Box<Process>, ~[Option<PipeWatcher>]), UvError> {
|
||||||
{
|
|
||||||
let cwd = config.cwd.map(|s| s.to_c_str());
|
let cwd = config.cwd.map(|s| s.to_c_str());
|
||||||
let mut io = vec![config.stdin, config.stdout, config.stderr];
|
let mut io = vec![config.stdin, config.stdout, config.stderr];
|
||||||
for slot in config.extra_io.iter() {
|
for slot in config.extra_io.iter() {
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::cast;
|
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
|
use std::cast;
|
||||||
use std::rt::task::BlockedTask;
|
use std::rt::task::BlockedTask;
|
||||||
use std::unstable::mutex::NativeMutex;
|
use std::unstable::mutex::NativeMutex;
|
||||||
use std::sync::arc::UnsafeArc;
|
use std::sync::arc::UnsafeArc;
|
||||||
|
@ -107,7 +107,7 @@ extern fn async_cb(handle: *uvll::uv_async_t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueuePool {
|
impl QueuePool {
|
||||||
pub fn new(loop_: &mut Loop) -> ~QueuePool {
|
pub fn new(loop_: &mut Loop) -> Box<QueuePool> {
|
||||||
let handle = UvHandle::alloc(None::<AsyncWatcher>, uvll::UV_ASYNC);
|
let handle = UvHandle::alloc(None::<AsyncWatcher>, uvll::UV_ASYNC);
|
||||||
let state = UnsafeArc::new(State {
|
let state = UnsafeArc::new(State {
|
||||||
handle: handle,
|
handle: handle,
|
||||||
|
|
|
@ -26,8 +26,8 @@ pub struct SignalWatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SignalWatcher {
|
impl SignalWatcher {
|
||||||
pub fn new(io: &mut UvIoFactory, signum: Signum,
|
pub fn new(io: &mut UvIoFactory, signum: Signum, channel: Sender<Signum>)
|
||||||
channel: Sender<Signum>) -> Result<~SignalWatcher, UvError> {
|
-> Result<Box<SignalWatcher>, UvError> {
|
||||||
let s = box SignalWatcher {
|
let s = box SignalWatcher {
|
||||||
handle: UvHandle::alloc(None::<SignalWatcher>, uvll::UV_SIGNAL),
|
handle: UvHandle::alloc(None::<SignalWatcher>, uvll::UV_SIGNAL),
|
||||||
home: io.make_handle(),
|
home: io.make_handle(),
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub enum NextAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimerWatcher {
|
impl TimerWatcher {
|
||||||
pub fn new(io: &mut UvIoFactory) -> ~TimerWatcher {
|
pub fn new(io: &mut UvIoFactory) -> Box<TimerWatcher> {
|
||||||
let handle = io.make_handle();
|
let handle = io.make_handle();
|
||||||
let me = box TimerWatcher::new_home(&io.loop_, handle);
|
let me = box TimerWatcher::new_home(&io.loop_, handle);
|
||||||
me.install()
|
me.install()
|
||||||
|
|
|
@ -93,17 +93,16 @@ impl EventLoop for UvEventLoop {
|
||||||
IdleWatcher::onetime(&mut self.uvio.loop_, f);
|
IdleWatcher::onetime(&mut self.uvio.loop_, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pausable_idle_callback(&mut self, cb: ~rtio::Callback:Send)
|
fn pausable_idle_callback(&mut self, cb: Box<rtio::Callback:Send>)
|
||||||
-> ~rtio::PausableIdleCallback:Send
|
-> Box<rtio::PausableIdleCallback:Send> {
|
||||||
{
|
IdleWatcher::new(&mut self.uvio.loop_, cb)
|
||||||
IdleWatcher::new(&mut self.uvio.loop_,
|
as Box<rtio::PausableIdleCallback:Send>
|
||||||
cb) as ~rtio::PausableIdleCallback:Send
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remote_callback(&mut self, f: ~rtio::Callback:Send)
|
fn remote_callback(&mut self, f: Box<rtio::Callback:Send>)
|
||||||
-> ~rtio::RemoteCallback:Send
|
-> Box<rtio::RemoteCallback:Send> {
|
||||||
{
|
box AsyncWatcher::new(&mut self.uvio.loop_, f) as
|
||||||
box AsyncWatcher::new(&mut self.uvio.loop_, f) as ~rtio::RemoteCallback:Send
|
Box<rtio::RemoteCallback:Send>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn io<'a>(&'a mut self) -> Option<&'a mut rtio::IoFactory> {
|
fn io<'a>(&'a mut self) -> Option<&'a mut rtio::IoFactory> {
|
||||||
|
@ -132,7 +131,7 @@ fn test_callback_run_once() {
|
||||||
|
|
||||||
pub struct UvIoFactory {
|
pub struct UvIoFactory {
|
||||||
pub loop_: Loop,
|
pub loop_: Loop,
|
||||||
handle_pool: Option<~QueuePool>,
|
handle_pool: Option<Box<QueuePool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UvIoFactory {
|
impl UvIoFactory {
|
||||||
|
@ -151,30 +150,31 @@ impl IoFactory for UvIoFactory {
|
||||||
// NB: This blocks the task waiting on the connection.
|
// NB: This blocks the task waiting on the connection.
|
||||||
// It would probably be better to return a future
|
// It would probably be better to return a future
|
||||||
fn tcp_connect(&mut self, addr: SocketAddr, timeout: Option<u64>)
|
fn tcp_connect(&mut self, addr: SocketAddr, timeout: Option<u64>)
|
||||||
-> Result<~rtio::RtioTcpStream:Send, IoError>
|
-> Result<Box<rtio::RtioTcpStream:Send>, IoError> {
|
||||||
{
|
|
||||||
match TcpWatcher::connect(self, addr, timeout) {
|
match TcpWatcher::connect(self, addr, timeout) {
|
||||||
Ok(t) => Ok(box t as ~rtio::RtioTcpStream:Send),
|
Ok(t) => Ok(box t as Box<rtio::RtioTcpStream:Send>),
|
||||||
Err(e) => Err(uv_error_to_io_error(e)),
|
Err(e) => Err(uv_error_to_io_error(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tcp_bind(&mut self, addr: SocketAddr) -> Result<~rtio::RtioTcpListener:Send, IoError> {
|
fn tcp_bind(&mut self, addr: SocketAddr)
|
||||||
|
-> Result<Box<rtio::RtioTcpListener:Send>, IoError> {
|
||||||
match TcpListener::bind(self, addr) {
|
match TcpListener::bind(self, addr) {
|
||||||
Ok(t) => Ok(t as ~rtio::RtioTcpListener:Send),
|
Ok(t) => Ok(t as Box<rtio::RtioTcpListener:Send>),
|
||||||
Err(e) => Err(uv_error_to_io_error(e)),
|
Err(e) => Err(uv_error_to_io_error(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn udp_bind(&mut self, addr: SocketAddr) -> Result<~rtio::RtioUdpSocket:Send, IoError> {
|
fn udp_bind(&mut self, addr: SocketAddr)
|
||||||
|
-> Result<Box<rtio::RtioUdpSocket:Send>, IoError> {
|
||||||
match UdpWatcher::bind(self, addr) {
|
match UdpWatcher::bind(self, addr) {
|
||||||
Ok(u) => Ok(box u as ~rtio::RtioUdpSocket:Send),
|
Ok(u) => Ok(box u as Box<rtio::RtioUdpSocket:Send>),
|
||||||
Err(e) => Err(uv_error_to_io_error(e)),
|
Err(e) => Err(uv_error_to_io_error(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timer_init(&mut self) -> Result<~rtio::RtioTimer:Send, IoError> {
|
fn timer_init(&mut self) -> Result<Box<rtio::RtioTimer:Send>, IoError> {
|
||||||
Ok(TimerWatcher::new(self) as ~rtio::RtioTimer:Send)
|
Ok(TimerWatcher::new(self) as Box<rtio::RtioTimer:Send>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
|
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
|
||||||
|
@ -183,13 +183,14 @@ impl IoFactory for UvIoFactory {
|
||||||
r.map_err(uv_error_to_io_error)
|
r.map_err(uv_error_to_io_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fs_from_raw_fd(&mut self, fd: c_int,
|
fn fs_from_raw_fd(&mut self, fd: c_int, close: rtio::CloseBehavior)
|
||||||
close: rtio::CloseBehavior) -> ~rtio::RtioFileStream:Send {
|
-> Box<rtio::RtioFileStream:Send> {
|
||||||
box FileWatcher::new(self, fd, close) as ~rtio::RtioFileStream:Send
|
box FileWatcher::new(self, fd, close) as
|
||||||
|
Box<rtio::RtioFileStream:Send>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
|
fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
|
||||||
-> Result<~rtio::RtioFileStream:Send, IoError> {
|
-> Result<Box<rtio::RtioFileStream:Send>, IoError> {
|
||||||
let flags = match fm {
|
let flags = match fm {
|
||||||
io::Open => 0,
|
io::Open => 0,
|
||||||
io::Append => libc::O_APPEND,
|
io::Append => libc::O_APPEND,
|
||||||
|
@ -205,7 +206,7 @@ impl IoFactory for UvIoFactory {
|
||||||
};
|
};
|
||||||
|
|
||||||
match FsRequest::open(self, path, flags as int, mode as int) {
|
match FsRequest::open(self, path, flags as int, mode as int) {
|
||||||
Ok(fs) => Ok(box fs as ~rtio::RtioFileStream:Send),
|
Ok(fs) => Ok(box fs as Box<rtio::RtioFileStream:Send>),
|
||||||
Err(e) => Err(uv_error_to_io_error(e))
|
Err(e) => Err(uv_error_to_io_error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,12 +271,16 @@ impl IoFactory for UvIoFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn(&mut self, config: ProcessConfig)
|
fn spawn(&mut self, config: ProcessConfig)
|
||||||
-> Result<(~rtio::RtioProcess:Send, ~[Option<~rtio::RtioPipe:Send>]), IoError>
|
-> Result<(Box<rtio::RtioProcess:Send>,
|
||||||
|
~[Option<Box<rtio::RtioPipe:Send>>]),
|
||||||
|
IoError>
|
||||||
{
|
{
|
||||||
match Process::spawn(self, config) {
|
match Process::spawn(self, config) {
|
||||||
Ok((p, io)) => {
|
Ok((p, io)) => {
|
||||||
Ok((p as ~rtio::RtioProcess:Send,
|
Ok((p as Box<rtio::RtioProcess:Send>,
|
||||||
io.move_iter().map(|i| i.map(|p| box p as ~rtio::RtioPipe:Send)).collect()))
|
io.move_iter().map(|i| i.map(|p| {
|
||||||
|
box p as Box<rtio::RtioPipe:Send>
|
||||||
|
})).collect()))
|
||||||
}
|
}
|
||||||
Err(e) => Err(uv_error_to_io_error(e)),
|
Err(e) => Err(uv_error_to_io_error(e)),
|
||||||
}
|
}
|
||||||
|
@ -285,41 +290,42 @@ impl IoFactory for UvIoFactory {
|
||||||
Process::kill(pid, signum).map_err(uv_error_to_io_error)
|
Process::kill(pid, signum).map_err(uv_error_to_io_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unix_bind(&mut self, path: &CString) -> Result<~rtio::RtioUnixListener:Send, IoError>
|
fn unix_bind(&mut self, path: &CString)
|
||||||
{
|
-> Result<Box<rtio::RtioUnixListener:Send>, IoError> {
|
||||||
match PipeListener::bind(self, path) {
|
match PipeListener::bind(self, path) {
|
||||||
Ok(p) => Ok(p as ~rtio::RtioUnixListener:Send),
|
Ok(p) => Ok(p as Box<rtio::RtioUnixListener:Send>),
|
||||||
Err(e) => Err(uv_error_to_io_error(e)),
|
Err(e) => Err(uv_error_to_io_error(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unix_connect(&mut self, path: &CString,
|
fn unix_connect(&mut self, path: &CString, timeout: Option<u64>)
|
||||||
timeout: Option<u64>) -> Result<~rtio::RtioPipe:Send, IoError> {
|
-> Result<Box<rtio::RtioPipe:Send>, IoError> {
|
||||||
match PipeWatcher::connect(self, path, timeout) {
|
match PipeWatcher::connect(self, path, timeout) {
|
||||||
Ok(p) => Ok(box p as ~rtio::RtioPipe:Send),
|
Ok(p) => Ok(box p as Box<rtio::RtioPipe:Send>),
|
||||||
Err(e) => Err(uv_error_to_io_error(e)),
|
Err(e) => Err(uv_error_to_io_error(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tty_open(&mut self, fd: c_int, readable: bool)
|
fn tty_open(&mut self, fd: c_int, readable: bool)
|
||||||
-> Result<~rtio::RtioTTY:Send, IoError> {
|
-> Result<Box<rtio::RtioTTY:Send>, IoError> {
|
||||||
match TtyWatcher::new(self, fd, readable) {
|
match TtyWatcher::new(self, fd, readable) {
|
||||||
Ok(tty) => Ok(box tty as ~rtio::RtioTTY:Send),
|
Ok(tty) => Ok(box tty as Box<rtio::RtioTTY:Send>),
|
||||||
Err(e) => Err(uv_error_to_io_error(e))
|
Err(e) => Err(uv_error_to_io_error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pipe_open(&mut self, fd: c_int) -> Result<~rtio::RtioPipe:Send, IoError> {
|
fn pipe_open(&mut self, fd: c_int)
|
||||||
|
-> Result<Box<rtio::RtioPipe:Send>, IoError> {
|
||||||
match PipeWatcher::open(self, fd) {
|
match PipeWatcher::open(self, fd) {
|
||||||
Ok(s) => Ok(box s as ~rtio::RtioPipe:Send),
|
Ok(s) => Ok(box s as Box<rtio::RtioPipe:Send>),
|
||||||
Err(e) => Err(uv_error_to_io_error(e))
|
Err(e) => Err(uv_error_to_io_error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signal(&mut self, signum: Signum, channel: Sender<Signum>)
|
fn signal(&mut self, signum: Signum, channel: Sender<Signum>)
|
||||||
-> Result<~rtio::RtioSignal:Send, IoError> {
|
-> Result<Box<rtio::RtioSignal:Send>, IoError> {
|
||||||
match SignalWatcher::new(self, signum, channel) {
|
match SignalWatcher::new(self, signum, channel) {
|
||||||
Ok(s) => Ok(s as ~rtio::RtioSignal:Send),
|
Ok(s) => Ok(s as Box<rtio::RtioSignal:Send>),
|
||||||
Err(e) => Err(uv_error_to_io_error(e)),
|
Err(e) => Err(uv_error_to_io_error(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ pub struct MyStruct {
|
||||||
|
|
||||||
impl ToJson for MyStruct {
|
impl ToJson for MyStruct {
|
||||||
fn to_json( &self ) -> json::Json {
|
fn to_json( &self ) -> json::Json {
|
||||||
let mut d = ~TreeMap::new();
|
let mut d = box TreeMap::new();
|
||||||
d.insert("attr1".to_owned(), self.attr1.to_json());
|
d.insert("attr1".to_owned(), self.attr1.to_json());
|
||||||
d.insert("attr2".to_owned(), self.attr2.to_json());
|
d.insert("attr2".to_owned(), self.attr2.to_json());
|
||||||
json::Object(d)
|
json::Object(d)
|
||||||
|
@ -206,7 +206,7 @@ pub struct TestStruct1 {
|
||||||
|
|
||||||
impl ToJson for TestStruct1 {
|
impl ToJson for TestStruct1 {
|
||||||
fn to_json( &self ) -> json::Json {
|
fn to_json( &self ) -> json::Json {
|
||||||
let mut d = ~TreeMap::new();
|
let mut d = box TreeMap::new();
|
||||||
d.insert("data_int".to_owned(), self.data_int.to_json());
|
d.insert("data_int".to_owned(), self.data_int.to_json());
|
||||||
d.insert("data_str".to_owned(), self.data_str.to_json());
|
d.insert("data_str".to_owned(), self.data_str.to_json());
|
||||||
d.insert("data_vector".to_owned(), self.data_vector.to_json());
|
d.insert("data_vector".to_owned(), self.data_vector.to_json());
|
||||||
|
@ -232,21 +232,20 @@ fn main() {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use collections::HashMap;
|
|
||||||
use std::char;
|
use std::char;
|
||||||
use std::f64;
|
use std::f64;
|
||||||
|
use std::fmt;
|
||||||
use std::io::MemWriter;
|
use std::io::MemWriter;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::num;
|
|
||||||
use std::str;
|
|
||||||
use std::str::ScalarValue;
|
|
||||||
use std::strbuf::StrBuf;
|
|
||||||
use std::fmt;
|
|
||||||
use std::vec::Vec;
|
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
|
use std::num;
|
||||||
|
use std::str::ScalarValue;
|
||||||
|
use std::str;
|
||||||
|
use std::strbuf::StrBuf;
|
||||||
|
use std::vec::Vec;
|
||||||
|
|
||||||
use Encodable;
|
use Encodable;
|
||||||
use collections::TreeMap;
|
use collections::{HashMap, TreeMap};
|
||||||
|
|
||||||
/// Represents a json value
|
/// Represents a json value
|
||||||
#[deriving(Clone, Eq)]
|
#[deriving(Clone, Eq)]
|
||||||
|
@ -255,7 +254,7 @@ pub enum Json {
|
||||||
String(~str),
|
String(~str),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
List(List),
|
List(List),
|
||||||
Object(~Object),
|
Object(Box<Object>),
|
||||||
Null,
|
Null,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -391,14 +391,14 @@ impl<'a, E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for &'a T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for ~T {
|
impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Box<T> {
|
||||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||||
(**self).encode(s)
|
(**self).encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for ~T {
|
impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Box<T> {
|
||||||
fn decode(d: &mut D) -> Result<~T, E> {
|
fn decode(d: &mut D) -> Result<Box<T>, E> {
|
||||||
Ok(box try!(Decodable::decode(d)))
|
Ok(box try!(Decodable::decode(d)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,13 @@
|
||||||
//! As `&Any` (a borrowed trait object), it has the `is` and `as_ref` methods, to test if the
|
//! As `&Any` (a borrowed trait object), it has the `is` and `as_ref` methods, to test if the
|
||||||
//! contained value is of a given type, and to get a reference to the inner value as a type. As
|
//! contained value is of a given type, and to get a reference to the inner value as a type. As
|
||||||
//! `&mut Any`, there is also the `as_mut` method, for getting a mutable reference to the inner
|
//! `&mut Any`, there is also the `as_mut` method, for getting a mutable reference to the inner
|
||||||
//! value. `~Any` adds the `move` method, which will unwrap a `~T` from the object. See the
|
//! value. `Box<Any>` adds the `move` method, which will unwrap a `Box<T>` from the object. See
|
||||||
//! extension traits (`*Ext`) for the full details.
|
//! the extension traits (`*Ext`) for the full details.
|
||||||
|
|
||||||
use cast::{transmute, transmute_copy};
|
use cast::{transmute, transmute_copy};
|
||||||
use fmt;
|
use fmt;
|
||||||
use option::{Option, Some, None};
|
use option::{Option, Some, None};
|
||||||
|
use owned::Box;
|
||||||
use raw::TraitObject;
|
use raw::TraitObject;
|
||||||
use result::{Result, Ok, Err};
|
use result::{Result, Ok, Err};
|
||||||
use intrinsics::TypeId;
|
use intrinsics::TypeId;
|
||||||
|
@ -121,12 +122,12 @@ impl<'a> AnyMutRefExt<'a> for &'a mut Any {
|
||||||
pub trait AnyOwnExt {
|
pub trait AnyOwnExt {
|
||||||
/// Returns the boxed value if it is of type `T`, or
|
/// Returns the boxed value if it is of type `T`, or
|
||||||
/// `Err(Self)` if it isn't.
|
/// `Err(Self)` if it isn't.
|
||||||
fn move<T: 'static>(self) -> Result<~T, Self>;
|
fn move<T: 'static>(self) -> Result<Box<T>, Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnyOwnExt for ~Any {
|
impl AnyOwnExt for Box<Any> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn move<T: 'static>(self) -> Result<~T, ~Any> {
|
fn move<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
|
||||||
if self.is::<T>() {
|
if self.is::<T>() {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Get the raw representation of the trait object
|
// Get the raw representation of the trait object
|
||||||
|
@ -148,9 +149,9 @@ impl AnyOwnExt for ~Any {
|
||||||
// Trait implementations
|
// Trait implementations
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl fmt::Show for ~Any {
|
impl fmt::Show for Box<Any> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
f.pad("~Any")
|
f.pad("Box<Any>")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +165,7 @@ impl<'a> fmt::Show for &'a Any {
|
||||||
mod tests {
|
mod tests {
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use owned::Box;
|
||||||
use str::StrSlice;
|
use str::StrSlice;
|
||||||
|
|
||||||
#[deriving(Eq, Show)]
|
#[deriving(Eq, Show)]
|
||||||
|
@ -190,7 +192,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn any_owning() {
|
fn any_owning() {
|
||||||
let (a, b, c) = (box 5u as ~Any, box TEST as ~Any, box Test as ~Any);
|
let (a, b, c) = (box 5u as Box<Any>, box TEST as Box<Any>, box Test as Box<Any>);
|
||||||
|
|
||||||
assert!(a.is::<uint>());
|
assert!(a.is::<uint>());
|
||||||
assert!(!b.is::<uint>());
|
assert!(!b.is::<uint>());
|
||||||
|
@ -268,8 +270,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn any_move() {
|
fn any_move() {
|
||||||
let a = box 8u as ~Any;
|
let a = box 8u as Box<Any>;
|
||||||
let b = box Test as ~Any;
|
let b = box Test as Box<Any>;
|
||||||
|
|
||||||
match a.move::<uint>() {
|
match a.move::<uint>() {
|
||||||
Ok(a) => { assert_eq!(a, box 8u); }
|
Ok(a) => { assert_eq!(a, box 8u); }
|
||||||
|
@ -280,19 +282,19 @@ mod tests {
|
||||||
Err(..) => fail!()
|
Err(..) => fail!()
|
||||||
}
|
}
|
||||||
|
|
||||||
let a = box 8u as ~Any;
|
let a = box 8u as Box<Any>;
|
||||||
let b = box Test as ~Any;
|
let b = box Test as Box<Any>;
|
||||||
|
|
||||||
assert!(a.move::<~Test>().is_err());
|
assert!(a.move::<Box<Test>>().is_err());
|
||||||
assert!(b.move::<~uint>().is_err());
|
assert!(b.move::<Box<uint>>().is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_show() {
|
fn test_show() {
|
||||||
let a = box 8u as ~Any;
|
let a = box 8u as Box<Any>;
|
||||||
let b = box Test as ~Any;
|
let b = box Test as Box<Any>;
|
||||||
assert_eq!(format!("{}", a), "~Any".to_owned());
|
assert_eq!(format!("{}", a), "Box<Any>".to_owned());
|
||||||
assert_eq!(format!("{}", b), "~Any".to_owned());
|
assert_eq!(format!("{}", b), "Box<Any>".to_owned());
|
||||||
|
|
||||||
let a = &8u as &Any;
|
let a = &8u as &Any;
|
||||||
let b = &Test as &Any;
|
let b = &Test as &Any;
|
||||||
|
|
|
@ -21,6 +21,8 @@ the `clone` method.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use owned::Box;
|
||||||
|
|
||||||
/// A common trait for cloning an object.
|
/// A common trait for cloning an object.
|
||||||
pub trait Clone {
|
pub trait Clone {
|
||||||
/// Returns a copy of the value. The contents of owned pointers
|
/// Returns a copy of the value. The contents of owned pointers
|
||||||
|
@ -39,14 +41,14 @@ pub trait Clone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone> Clone for ~T {
|
impl<T: Clone> Clone for Box<T> {
|
||||||
/// Return a copy of the owned box.
|
/// Return a copy of the owned box.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> ~T { box {(**self).clone()} }
|
fn clone(&self) -> Box<T> { box {(**self).clone()} }
|
||||||
|
|
||||||
/// Perform copy-assignment from `source` by reusing the existing allocation.
|
/// Perform copy-assignment from `source` by reusing the existing allocation.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone_from(&mut self, source: &~T) {
|
fn clone_from(&mut self, source: &Box<T>) {
|
||||||
(**self).clone_from(&(**source));
|
(**self).clone_from(&(**source));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +129,7 @@ extern_fn_clone!(A, B, C, D, E, F, G, H)
|
||||||
#[test]
|
#[test]
|
||||||
fn test_owned_clone() {
|
fn test_owned_clone() {
|
||||||
let a = box 5i;
|
let a = box 5i;
|
||||||
let b: ~int = a.clone();
|
let b: Box<int> = a.clone();
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -279,6 +279,7 @@ use kinds::marker;
|
||||||
use mem;
|
use mem;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use option::{Some, None, Option};
|
use option::{Some, None, Option};
|
||||||
|
use owned::Box;
|
||||||
use result::{Ok, Err, Result};
|
use result::{Ok, Err, Result};
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
use rt::task::{Task, BlockedTask};
|
use rt::task::{Task, BlockedTask};
|
||||||
|
@ -297,6 +298,7 @@ macro_rules! test (
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
|
use owned::Box;
|
||||||
use task;
|
use task;
|
||||||
|
|
||||||
fn f() $b
|
fn f() $b
|
||||||
|
@ -549,7 +551,7 @@ impl<T: Send> Sender<T> {
|
||||||
let cnt = self.sends.get() + 1;
|
let cnt = self.sends.get() + 1;
|
||||||
self.sends.set(cnt);
|
self.sends.set(cnt);
|
||||||
if cnt % (RESCHED_FREQ as uint) == 0 {
|
if cnt % (RESCHED_FREQ as uint) == 0 {
|
||||||
let task: Option<~Task> = Local::try_take();
|
let task: Option<Box<Task>> = Local::try_take();
|
||||||
task.map(|t| t.maybe_yield());
|
task.map(|t| t.maybe_yield());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +775,7 @@ impl<T: Send> Receiver<T> {
|
||||||
let cnt = self.receives.get() + 1;
|
let cnt = self.receives.get() + 1;
|
||||||
self.receives.set(cnt);
|
self.receives.set(cnt);
|
||||||
if cnt % (RESCHED_FREQ as uint) == 0 {
|
if cnt % (RESCHED_FREQ as uint) == 0 {
|
||||||
let task: Option<~Task> = Local::try_take();
|
let task: Option<Box<Task>> = Local::try_take();
|
||||||
task.map(|t| t.maybe_yield());
|
task.map(|t| t.maybe_yield());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,6 +981,7 @@ mod test {
|
||||||
|
|
||||||
use native;
|
use native;
|
||||||
use os;
|
use os;
|
||||||
|
use owned::Box;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn stress_factor() -> uint {
|
pub fn stress_factor() -> uint {
|
||||||
|
@ -1197,7 +1200,7 @@ mod test {
|
||||||
|
|
||||||
test!(fn oneshot_single_thread_send_port_close() {
|
test!(fn oneshot_single_thread_send_port_close() {
|
||||||
// Testing that the sender cleans up the payload if receiver is closed
|
// Testing that the sender cleans up the payload if receiver is closed
|
||||||
let (tx, rx) = channel::<~int>();
|
let (tx, rx) = channel::<Box<int>>();
|
||||||
drop(rx);
|
drop(rx);
|
||||||
tx.send(box 0);
|
tx.send(box 0);
|
||||||
} #[should_fail])
|
} #[should_fail])
|
||||||
|
@ -1214,7 +1217,7 @@ mod test {
|
||||||
})
|
})
|
||||||
|
|
||||||
test!(fn oneshot_single_thread_send_then_recv() {
|
test!(fn oneshot_single_thread_send_then_recv() {
|
||||||
let (tx, rx) = channel::<~int>();
|
let (tx, rx) = channel::<Box<int>>();
|
||||||
tx.send(box 10);
|
tx.send(box 10);
|
||||||
assert!(rx.recv() == box 10);
|
assert!(rx.recv() == box 10);
|
||||||
})
|
})
|
||||||
|
@ -1263,7 +1266,7 @@ mod test {
|
||||||
})
|
})
|
||||||
|
|
||||||
test!(fn oneshot_multi_task_recv_then_send() {
|
test!(fn oneshot_multi_task_recv_then_send() {
|
||||||
let (tx, rx) = channel::<~int>();
|
let (tx, rx) = channel::<Box<int>>();
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
assert!(rx.recv() == box 10);
|
assert!(rx.recv() == box 10);
|
||||||
});
|
});
|
||||||
|
@ -1272,7 +1275,7 @@ mod test {
|
||||||
})
|
})
|
||||||
|
|
||||||
test!(fn oneshot_multi_task_recv_then_close() {
|
test!(fn oneshot_multi_task_recv_then_close() {
|
||||||
let (tx, rx) = channel::<~int>();
|
let (tx, rx) = channel::<Box<int>>();
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
drop(tx);
|
drop(tx);
|
||||||
});
|
});
|
||||||
|
@ -1340,7 +1343,7 @@ mod test {
|
||||||
send(tx, 0);
|
send(tx, 0);
|
||||||
recv(rx, 0);
|
recv(rx, 0);
|
||||||
|
|
||||||
fn send(tx: Sender<~int>, i: int) {
|
fn send(tx: Sender<Box<int>>, i: int) {
|
||||||
if i == 10 { return }
|
if i == 10 { return }
|
||||||
|
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
|
@ -1349,7 +1352,7 @@ mod test {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recv(rx: Receiver<~int>, i: int) {
|
fn recv(rx: Receiver<Box<int>>, i: int) {
|
||||||
if i == 10 { return }
|
if i == 10 { return }
|
||||||
|
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
|
@ -1513,6 +1516,7 @@ mod test {
|
||||||
mod sync_tests {
|
mod sync_tests {
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
use os;
|
use os;
|
||||||
|
use owned::Box;
|
||||||
|
|
||||||
pub fn stress_factor() -> uint {
|
pub fn stress_factor() -> uint {
|
||||||
match os::getenv("RUST_TEST_STRESS") {
|
match os::getenv("RUST_TEST_STRESS") {
|
||||||
|
@ -1657,7 +1661,7 @@ mod sync_tests {
|
||||||
|
|
||||||
test!(fn oneshot_single_thread_send_port_close() {
|
test!(fn oneshot_single_thread_send_port_close() {
|
||||||
// Testing that the sender cleans up the payload if receiver is closed
|
// Testing that the sender cleans up the payload if receiver is closed
|
||||||
let (tx, rx) = sync_channel::<~int>(0);
|
let (tx, rx) = sync_channel::<Box<int>>(0);
|
||||||
drop(rx);
|
drop(rx);
|
||||||
tx.send(box 0);
|
tx.send(box 0);
|
||||||
} #[should_fail])
|
} #[should_fail])
|
||||||
|
@ -1674,7 +1678,7 @@ mod sync_tests {
|
||||||
})
|
})
|
||||||
|
|
||||||
test!(fn oneshot_single_thread_send_then_recv() {
|
test!(fn oneshot_single_thread_send_then_recv() {
|
||||||
let (tx, rx) = sync_channel::<~int>(1);
|
let (tx, rx) = sync_channel::<Box<int>>(1);
|
||||||
tx.send(box 10);
|
tx.send(box 10);
|
||||||
assert!(rx.recv() == box 10);
|
assert!(rx.recv() == box 10);
|
||||||
})
|
})
|
||||||
|
@ -1728,7 +1732,7 @@ mod sync_tests {
|
||||||
})
|
})
|
||||||
|
|
||||||
test!(fn oneshot_multi_task_recv_then_send() {
|
test!(fn oneshot_multi_task_recv_then_send() {
|
||||||
let (tx, rx) = sync_channel::<~int>(0);
|
let (tx, rx) = sync_channel::<Box<int>>(0);
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
assert!(rx.recv() == box 10);
|
assert!(rx.recv() == box 10);
|
||||||
});
|
});
|
||||||
|
@ -1737,7 +1741,7 @@ mod sync_tests {
|
||||||
})
|
})
|
||||||
|
|
||||||
test!(fn oneshot_multi_task_recv_then_close() {
|
test!(fn oneshot_multi_task_recv_then_close() {
|
||||||
let (tx, rx) = sync_channel::<~int>(0);
|
let (tx, rx) = sync_channel::<Box<int>>(0);
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
drop(tx);
|
drop(tx);
|
||||||
});
|
});
|
||||||
|
@ -1805,7 +1809,7 @@ mod sync_tests {
|
||||||
send(tx, 0);
|
send(tx, 0);
|
||||||
recv(rx, 0);
|
recv(rx, 0);
|
||||||
|
|
||||||
fn send(tx: SyncSender<~int>, i: int) {
|
fn send(tx: SyncSender<Box<int>>, i: int) {
|
||||||
if i == 10 { return }
|
if i == 10 { return }
|
||||||
|
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
|
@ -1814,7 +1818,7 @@ mod sync_tests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recv(rx: Receiver<~int>, i: int) {
|
fn recv(rx: Receiver<Box<int>>, i: int) {
|
||||||
if i == 10 { return }
|
if i == 10 { return }
|
||||||
|
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
|
|
|
@ -37,6 +37,7 @@ use kinds::Send;
|
||||||
use mem;
|
use mem;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use option::{Some, None, Option};
|
use option::{Some, None, Option};
|
||||||
|
use owned::Box;
|
||||||
use result::{Result, Ok, Err};
|
use result::{Result, Ok, Err};
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
use rt::task::{Task, BlockedTask};
|
use rt::task::{Task, BlockedTask};
|
||||||
|
@ -137,7 +138,7 @@ impl<T: Send> Packet<T> {
|
||||||
// Attempt to not block the task (it's a little expensive). If it looks
|
// Attempt to not block the task (it's a little expensive). If it looks
|
||||||
// like we're not empty, then immediately go through to `try_recv`.
|
// like we're not empty, then immediately go through to `try_recv`.
|
||||||
if self.state.load(atomics::SeqCst) == EMPTY {
|
if self.state.load(atomics::SeqCst) == EMPTY {
|
||||||
let t: ~Task = Local::take();
|
let t: Box<Task> = Local::take();
|
||||||
t.deschedule(1, |task| {
|
t.deschedule(1, |task| {
|
||||||
let n = unsafe { task.cast_to_uint() };
|
let n = unsafe { task.cast_to_uint() };
|
||||||
match self.state.compare_and_swap(EMPTY, n, atomics::SeqCst) {
|
match self.state.compare_and_swap(EMPTY, n, atomics::SeqCst) {
|
||||||
|
|
|
@ -52,6 +52,7 @@ use kinds::marker;
|
||||||
use kinds::Send;
|
use kinds::Send;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use option::{Some, None, Option};
|
use option::{Some, None, Option};
|
||||||
|
use owned::Box;
|
||||||
use ptr::RawPtr;
|
use ptr::RawPtr;
|
||||||
use result::{Ok, Err, Result};
|
use result::{Ok, Err, Result};
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
|
@ -176,7 +177,7 @@ impl Select {
|
||||||
// Acquire a number of blocking contexts, and block on each one
|
// Acquire a number of blocking contexts, and block on each one
|
||||||
// sequentially until one fails. If one fails, then abort
|
// sequentially until one fails. If one fails, then abort
|
||||||
// immediately so we can go unblock on all the other receivers.
|
// immediately so we can go unblock on all the other receivers.
|
||||||
let task: ~Task = Local::take();
|
let task: Box<Task> = Local::take();
|
||||||
task.deschedule(amt, |task| {
|
task.deschedule(amt, |task| {
|
||||||
// Prepare for the block
|
// Prepare for the block
|
||||||
let (i, handle) = iter.next().unwrap();
|
let (i, handle) = iter.next().unwrap();
|
||||||
|
|
|
@ -24,6 +24,7 @@ use iter::Iterator;
|
||||||
use kinds::Send;
|
use kinds::Send;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use option::{Some, None, Option};
|
use option::{Some, None, Option};
|
||||||
|
use owned::Box;
|
||||||
use result::{Ok, Err, Result};
|
use result::{Ok, Err, Result};
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
use rt::task::{Task, BlockedTask};
|
use rt::task::{Task, BlockedTask};
|
||||||
|
@ -223,7 +224,7 @@ impl<T: Send> Packet<T> {
|
||||||
data => return data,
|
data => return data,
|
||||||
}
|
}
|
||||||
|
|
||||||
let task: ~Task = Local::take();
|
let task: Box<Task> = Local::take();
|
||||||
task.deschedule(1, |task| {
|
task.deschedule(1, |task| {
|
||||||
self.decrement(task)
|
self.decrement(task)
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,6 +24,7 @@ use iter::Iterator;
|
||||||
use kinds::Send;
|
use kinds::Send;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use option::{Some, None};
|
use option::{Some, None};
|
||||||
|
use owned::Box;
|
||||||
use result::{Ok, Err, Result};
|
use result::{Ok, Err, Result};
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
use rt::task::{Task, BlockedTask};
|
use rt::task::{Task, BlockedTask};
|
||||||
|
@ -181,7 +182,7 @@ impl<T: Send> Packet<T> {
|
||||||
|
|
||||||
// Welp, our channel has no data. Deschedule the current task and
|
// Welp, our channel has no data. Deschedule the current task and
|
||||||
// initiate the blocking protocol.
|
// initiate the blocking protocol.
|
||||||
let task: ~Task = Local::take();
|
let task: Box<Task> = Local::take();
|
||||||
task.deschedule(1, |task| {
|
task.deschedule(1, |task| {
|
||||||
self.decrement(task)
|
self.decrement(task)
|
||||||
});
|
});
|
||||||
|
|
|
@ -40,6 +40,7 @@ use kinds::Send;
|
||||||
use mem;
|
use mem;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use option::{Some, None, Option};
|
use option::{Some, None, Option};
|
||||||
|
use owned::Box;
|
||||||
use ptr::RawPtr;
|
use ptr::RawPtr;
|
||||||
use result::{Result, Ok, Err};
|
use result::{Result, Ok, Err};
|
||||||
use rt::local::Local;
|
use rt::local::Local;
|
||||||
|
@ -111,7 +112,7 @@ pub enum Failure {
|
||||||
/// in the meantime. This re-locks the mutex upon returning.
|
/// in the meantime. This re-locks the mutex upon returning.
|
||||||
fn wait(slot: &mut Blocker, f: fn(BlockedTask) -> Blocker,
|
fn wait(slot: &mut Blocker, f: fn(BlockedTask) -> Blocker,
|
||||||
lock: &NativeMutex) {
|
lock: &NativeMutex) {
|
||||||
let me: ~Task = Local::take();
|
let me: Box<Task> = Local::take();
|
||||||
me.deschedule(1, |task| {
|
me.deschedule(1, |task| {
|
||||||
match mem::replace(slot, f(task)) {
|
match mem::replace(slot, f(task)) {
|
||||||
NoneBlocked => {}
|
NoneBlocked => {}
|
||||||
|
@ -445,7 +446,7 @@ impl<T> Buffer<T> {
|
||||||
|
|
||||||
impl Queue {
|
impl Queue {
|
||||||
fn enqueue(&mut self, lock: &NativeMutex) {
|
fn enqueue(&mut self, lock: &NativeMutex) {
|
||||||
let task: ~Task = Local::take();
|
let task: Box<Task> = Local::take();
|
||||||
let mut node = Node {
|
let mut node = Node {
|
||||||
task: None,
|
task: None,
|
||||||
next: 0 as *mut Node,
|
next: 0 as *mut Node,
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
//! The `Default` trait for types which may have meaningful default values
|
//! The `Default` trait for types which may have meaningful default values
|
||||||
|
|
||||||
|
use owned::Box;
|
||||||
|
|
||||||
/// A trait that types which have a useful default value should implement.
|
/// A trait that types which have a useful default value should implement.
|
||||||
pub trait Default {
|
pub trait Default {
|
||||||
/// Return the "default value" for a type.
|
/// Return the "default value" for a type.
|
||||||
|
@ -20,6 +22,6 @@ impl<T: Default + 'static> Default for @T {
|
||||||
fn default() -> @T { @Default::default() }
|
fn default() -> @T { @Default::default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Default> Default for ~T {
|
impl<T: Default> Default for Box<T> {
|
||||||
fn default() -> ~T { box Default::default() }
|
fn default() -> Box<T> { box Default::default() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -492,6 +492,7 @@ use io;
|
||||||
use iter::{Iterator, range};
|
use iter::{Iterator, range};
|
||||||
use num::Signed;
|
use num::Signed;
|
||||||
use option::{Option,Some,None};
|
use option::{Option,Some,None};
|
||||||
|
use owned::Box;
|
||||||
use repr;
|
use repr;
|
||||||
use result::{Ok, Err};
|
use result::{Ok, Err};
|
||||||
use str::StrSlice;
|
use str::StrSlice;
|
||||||
|
@ -1113,7 +1114,7 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> {
|
||||||
impl<T: Show> Show for @T {
|
impl<T: Show> Show for @T {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) }
|
fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) }
|
||||||
}
|
}
|
||||||
impl<T: Show> Show for ~T {
|
impl<T: Show> Show for Box<T> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) }
|
fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) }
|
||||||
}
|
}
|
||||||
impl<'a, T: Show> Show for &'a T {
|
impl<'a, T: Show> Show for &'a T {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
|
|
||||||
use char;
|
use char;
|
||||||
|
use owned::Box;
|
||||||
use str;
|
use str;
|
||||||
|
|
||||||
/// A piece is a portion of the format string which represents the next part
|
/// A piece is a portion of the format string which represents the next part
|
||||||
|
@ -41,7 +42,7 @@ pub struct Argument<'a> {
|
||||||
/// How to format the argument
|
/// How to format the argument
|
||||||
pub format: FormatSpec<'a>,
|
pub format: FormatSpec<'a>,
|
||||||
/// If not `None`, what method to invoke on the argument
|
/// If not `None`, what method to invoke on the argument
|
||||||
pub method: Option<~Method<'a>>
|
pub method: Option<Box<Method<'a>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specification for the formatting of an argument in the format string.
|
/// Specification for the formatting of an argument in the format string.
|
||||||
|
@ -435,7 +436,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parses a method to be applied to the previously specified argument and
|
/// Parses a method to be applied to the previously specified argument and
|
||||||
/// its format. The two current supported methods are 'plural' and 'select'
|
/// its format. The two current supported methods are 'plural' and 'select'
|
||||||
fn method(&mut self) -> Option<~Method<'a>> {
|
fn method(&mut self) -> Option<Box<Method<'a>>> {
|
||||||
if !self.wsconsume(',') {
|
if !self.wsconsume(',') {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -461,7 +462,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a 'select' statement (after the initial 'select' word)
|
/// Parses a 'select' statement (after the initial 'select' word)
|
||||||
fn select(&mut self) -> ~Method<'a> {
|
fn select(&mut self) -> Box<Method<'a>> {
|
||||||
let mut other = None;
|
let mut other = None;
|
||||||
let mut arms = vec!();
|
let mut arms = vec!();
|
||||||
// Consume arms one at a time
|
// Consume arms one at a time
|
||||||
|
@ -503,7 +504,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a 'plural' statement (after the initial 'plural' word)
|
/// Parses a 'plural' statement (after the initial 'plural' word)
|
||||||
fn plural(&mut self) -> ~Method<'a> {
|
fn plural(&mut self) -> Box<Method<'a>> {
|
||||||
let mut offset = None;
|
let mut offset = None;
|
||||||
let mut other = None;
|
let mut other = None;
|
||||||
let mut arms = vec!();
|
let mut arms = vec!();
|
||||||
|
|
|
@ -67,6 +67,7 @@ use container::Container;
|
||||||
use io::Writer;
|
use io::Writer;
|
||||||
use iter::Iterator;
|
use iter::Iterator;
|
||||||
use option::{Option, Some, None};
|
use option::{Option, Some, None};
|
||||||
|
use owned::Box;
|
||||||
use rc::Rc;
|
use rc::Rc;
|
||||||
use str::{Str, StrSlice};
|
use str::{Str, StrSlice};
|
||||||
use slice::{Vector, ImmutableVector};
|
use slice::{Vector, ImmutableVector};
|
||||||
|
@ -229,7 +230,7 @@ impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Writer, T: Hash<S>> Hash<S> for ~T {
|
impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
(**self).hash(state);
|
(**self).hash(state);
|
||||||
|
|
|
@ -55,11 +55,12 @@ use container::Container;
|
||||||
use iter::Iterator;
|
use iter::Iterator;
|
||||||
use kinds::Send;
|
use kinds::Send;
|
||||||
use super::{Reader, Writer, Seek};
|
use super::{Reader, Writer, Seek};
|
||||||
use super::{SeekStyle, Read, Write, Open, IoError, Truncate,
|
use super::{SeekStyle, Read, Write, Open, IoError, Truncate};
|
||||||
FileMode, FileAccess, FileStat, IoResult, FilePermission};
|
use super::{FileMode, FileAccess, FileStat, IoResult, FilePermission};
|
||||||
use rt::rtio::{RtioFileStream, IoFactory, LocalIo};
|
use rt::rtio::{RtioFileStream, IoFactory, LocalIo};
|
||||||
use io;
|
use io;
|
||||||
use option::{Some, None, Option};
|
use option::{Some, None, Option};
|
||||||
|
use owned::Box;
|
||||||
use result::{Ok, Err};
|
use result::{Ok, Err};
|
||||||
use path;
|
use path;
|
||||||
use path::{Path, GenericPath};
|
use path::{Path, GenericPath};
|
||||||
|
@ -78,7 +79,7 @@ use vec::Vec;
|
||||||
/// configured at creation time, via the `FileAccess` parameter to
|
/// configured at creation time, via the `FileAccess` parameter to
|
||||||
/// `File::open_mode()`.
|
/// `File::open_mode()`.
|
||||||
pub struct File {
|
pub struct File {
|
||||||
fd: ~RtioFileStream:Send,
|
fd: Box<RtioFileStream:Send>,
|
||||||
path: Path,
|
path: Path,
|
||||||
last_nread: int,
|
last_nread: int,
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue