Skip to content

Commit d062de8

Browse files
committed
auto merge of #9310 : pcwalton/rust/at-fn, r=pcwalton
r? @brson
2 parents 348d844 + 3b1d3e5 commit d062de8

File tree

147 files changed

+2854
-2929
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

147 files changed

+2854
-2929
lines changed

doc/tutorial.md

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,34 +1469,6 @@ cannot be stored in data structures or returned from
14691469
functions. Despite these limitations, stack closures are used
14701470
pervasively in Rust code.
14711471

1472-
## Managed closures
1473-
1474-
When you need to store a closure in a data structure, a stack closure
1475-
will not do, since the compiler will refuse to let you store it. For
1476-
this purpose, Rust provides a type of closure that has an arbitrary
1477-
lifetime, written `@fn` (boxed closure, analogous to the `@` pointer
1478-
type described earlier). This type of closure *is* first-class.
1479-
1480-
A managed closure does not directly access its environment, but merely
1481-
copies out the values that it closes over into a private data
1482-
structure. This means that it can not assign to these variables, and
1483-
cannot observe updates to them.
1484-
1485-
This code creates a closure that adds a given string to its argument,
1486-
returns it from a function, and then calls it:
1487-
1488-
~~~~
1489-
fn mk_appender(suffix: ~str) -> @fn(~str) -> ~str {
1490-
// The compiler knows that we intend this closure to be of type @fn
1491-
return |s| s + suffix;
1492-
}
1493-
1494-
fn main() {
1495-
let shout = mk_appender(~"!");
1496-
println(shout(~"hey ho, let's go"));
1497-
}
1498-
~~~~
1499-
15001472
## Owned closures
15011473

15021474
Owned closures, written `~fn` in analogy to the `~` pointer type,

src/libextra/c_vec.rs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,37 +36,39 @@
3636
* still held if needed.
3737
*/
3838

39-
40-
use std::option;
4139
use std::ptr;
40+
use std::routine::Runnable;
41+
use std::util;
4242

4343
/**
4444
* The type representing a foreign chunk of memory
45-
*
4645
*/
4746
pub struct CVec<T> {
4847
priv base: *mut T,
4948
priv len: uint,
50-
priv rsrc: @DtorRes
49+
priv rsrc: @DtorRes,
5150
}
5251

5352
struct DtorRes {
54-
dtor: Option<@fn()>,
53+
dtor: Option<~Runnable>,
5554
}
5655

5756
#[unsafe_destructor]
5857
impl Drop for DtorRes {
5958
fn drop(&mut self) {
60-
match self.dtor {
61-
option::None => (),
62-
option::Some(f) => f()
59+
let dtor = util::replace(&mut self.dtor, None);
60+
match dtor {
61+
None => (),
62+
Some(f) => f.run()
6363
}
6464
}
6565
}
6666

67-
fn DtorRes(dtor: Option<@fn()>) -> DtorRes {
68-
DtorRes {
69-
dtor: dtor
67+
impl DtorRes {
68+
fn new(dtor: Option<~Runnable>) -> DtorRes {
69+
DtorRes {
70+
dtor: dtor,
71+
}
7072
}
7173
}
7274

@@ -83,10 +85,10 @@ fn DtorRes(dtor: Option<@fn()>) -> DtorRes {
8385
* * len - The number of elements in the buffer
8486
*/
8587
pub unsafe fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
86-
return CVec{
88+
return CVec {
8789
base: base,
8890
len: len,
89-
rsrc: @DtorRes(option::None)
91+
rsrc: @DtorRes::new(None)
9092
};
9193
}
9294

@@ -101,12 +103,12 @@ pub unsafe fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
101103
* * dtor - A function to run when the value is destructed, useful
102104
* for freeing the buffer, etc.
103105
*/
104-
pub unsafe fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: @fn())
105-
-> CVec<T> {
106+
pub unsafe fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: ~Runnable)
107+
-> CVec<T> {
106108
return CVec{
107109
base: base,
108110
len: len,
109-
rsrc: @DtorRes(option::Some(dtor))
111+
rsrc: @DtorRes::new(Some(dtor))
110112
};
111113
}
112114

@@ -153,6 +155,20 @@ mod tests {
153155

154156
use std::libc::*;
155157
use std::libc;
158+
use std::routine::Runnable;
159+
160+
struct LibcFree {
161+
mem: *c_void,
162+
}
163+
164+
impl Runnable for LibcFree {
165+
#[fixed_stack_segment]
166+
fn run(~self) {
167+
unsafe {
168+
libc::free(self.mem)
169+
}
170+
}
171+
}
156172

157173
fn malloc(n: size_t) -> CVec<u8> {
158174
#[fixed_stack_segment];
@@ -163,12 +179,11 @@ mod tests {
163179

164180
assert!(mem as int != 0);
165181

166-
return c_vec_with_dtor(mem as *mut u8, n as uint, || f(mem));
167-
}
168-
169-
fn f(mem: *c_void) {
170-
#[fixed_stack_segment]; #[inline(never)];
171-
unsafe { libc::free(mem) }
182+
return c_vec_with_dtor(mem as *mut u8,
183+
n as uint,
184+
~LibcFree {
185+
mem: mem,
186+
} as ~Runnable);
172187
}
173188
}
174189

src/libextra/rl.rs

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub mod rustrt {
3030

3131
macro_rules! locked {
3232
($expr:expr) => {
33-
unsafe {
33+
{
3434
// FIXME #9105: can't use a static mutex in pure Rust yet.
3535
rustrt::rust_take_linenoise_lock();
3636
let x = $expr;
@@ -43,35 +43,46 @@ macro_rules! locked {
4343
/// Add a line to history
4444
pub fn add_history(line: &str) -> bool {
4545
do line.with_c_str |buf| {
46-
(locked!(rustrt::linenoiseHistoryAdd(buf))) == 1 as c_int
46+
unsafe {
47+
(locked!(rustrt::linenoiseHistoryAdd(buf))) == 1 as c_int
48+
}
4749
}
4850
}
4951

5052
/// Set the maximum amount of lines stored
5153
pub fn set_history_max_len(len: int) -> bool {
52-
(locked!(rustrt::linenoiseHistorySetMaxLen(len as c_int))) == 1 as c_int
54+
unsafe {
55+
(locked!(rustrt::linenoiseHistorySetMaxLen(len as c_int))) == 1
56+
as c_int
57+
}
5358
}
5459

5560
/// Save line history to a file
5661
pub fn save_history(file: &str) -> bool {
5762
do file.with_c_str |buf| {
5863
// 0 on success, -1 on failure
59-
(locked!(rustrt::linenoiseHistorySave(buf))) == 0 as c_int
64+
unsafe {
65+
(locked!(rustrt::linenoiseHistorySave(buf))) == 0 as c_int
66+
}
6067
}
6168
}
6269

6370
/// Load line history from a file
6471
pub fn load_history(file: &str) -> bool {
6572
do file.with_c_str |buf| {
6673
// 0 on success, -1 on failure
67-
(locked!(rustrt::linenoiseHistoryLoad(buf))) == 0 as c_int
74+
unsafe {
75+
(locked!(rustrt::linenoiseHistoryLoad(buf))) == 0 as c_int
76+
}
6877
}
6978
}
7079

7180
/// Print out a prompt and then wait for input and return it
7281
pub fn read(prompt: &str) -> Option<~str> {
7382
do prompt.with_c_str |buf| {
74-
let line = locked!(rustrt::linenoise(buf));
83+
let line = unsafe {
84+
locked!(rustrt::linenoise(buf))
85+
};
7586

7687
if line.is_null() { None }
7788
else {
@@ -88,35 +99,36 @@ pub fn read(prompt: &str) -> Option<~str> {
8899
}
89100
}
90101

91-
pub type CompletionCb = @fn(~str, @fn(~str));
102+
/// The callback used to perform completions.
103+
pub trait CompletionCb {
104+
/// Performs a completion.
105+
fn complete(&self, line: ~str, suggestion: &fn(~str));
106+
}
92107

93-
local_data_key!(complete_key: CompletionCb)
108+
local_data_key!(complete_key: @CompletionCb)
94109

95110
/// Bind to the main completion callback in the current task.
96111
///
97112
/// The completion callback should not call any `extra::rl` functions
98113
/// other than the closure that it receives as its second
99114
/// argument. Calling such a function will deadlock on the mutex used
100115
/// to ensure that the calls are thread-safe.
101-
pub fn complete(cb: CompletionCb) {
116+
pub unsafe fn complete(cb: @CompletionCb) {
102117
local_data::set(complete_key, cb);
103118

104-
extern fn callback(c_line: *c_char, completions: *()) {
119+
extern fn callback(line: *c_char, completions: *()) {
105120
do local_data::get(complete_key) |opt_cb| {
106121
// only fetch completions if a completion handler has been
107122
// registered in the current task.
108123
match opt_cb {
109-
None => {},
124+
None => {}
110125
Some(cb) => {
111-
let line = unsafe { str::raw::from_c_str(c_line) };
112-
do (*cb)(line) |suggestion| {
113-
do suggestion.with_c_str |buf| {
114-
// This isn't locked, because `callback` gets
115-
// called inside `rustrt::linenoise`, which
116-
// *is* already inside the mutex, so
117-
// re-locking would be a deadlock.
118-
unsafe {
119-
rustrt::linenoiseAddCompletion(completions, buf);
126+
unsafe {
127+
do cb.complete(str::raw::from_c_str(line))
128+
|suggestion| {
129+
do suggestion.with_c_str |buf| {
130+
rustrt::linenoiseAddCompletion(completions,
131+
buf);
120132
}
121133
}
122134
}

src/libextra/test.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -807,11 +807,6 @@ pub fn filter_tests(
807807
}
808808
}
809809

810-
struct TestFuture {
811-
test: TestDesc,
812-
wait: @fn() -> TestResult,
813-
}
814-
815810
pub fn run_test(force_ignore: bool,
816811
test: TestDescAndFn,
817812
monitor_ch: SharedChan<MonitorMsg>) {

0 commit comments

Comments
 (0)