提交 68ea9aed 编写于 作者: P Patrick Walton

librustc: Remove `@fn` managed closures from the language.

上级 9a4de3f3
......@@ -36,7 +36,6 @@
* still held if needed.
*/
use std::cast;
use std::ptr;
use std::routine::Runnable;
use std::util;
......@@ -57,9 +56,10 @@ struct DtorRes {
#[unsafe_destructor]
impl Drop for DtorRes {
fn drop(&mut self) {
match self.dtor {
option::None => (),
option::Some(f) => f()
let dtor = util::replace(&mut self.dtor, None);
match dtor {
None => (),
Some(f) => f.run()
}
}
}
......
......@@ -30,13 +30,11 @@ pub mod rustrt {
macro_rules! locked {
($expr:expr) => {
unsafe {
// FIXME #9105: can't use a static mutex in pure Rust yet.
rustrt::rust_take_linenoise_lock();
let x = $expr;
rustrt::rust_drop_linenoise_lock();
x
}
// FIXME #9105: can't use a static mutex in pure Rust yet.
rustrt::rust_take_linenoise_lock();
let x = $expr;
rustrt::rust_drop_linenoise_lock();
x
}
}
......@@ -88,9 +86,13 @@ pub fn read(prompt: &str) -> Option<~str> {
}
}
pub type CompletionCb = @fn(~str, @fn(~str));
/// The callback used to perform completions.
pub trait CompletionCb {
/// Performs a completion.
fn complete(&self, line: ~str, suggestion: &fn(~str));
}
local_data_key!(complete_key: CompletionCb)
local_data_key!(complete_key: @CompletionCb)
/// Bind to the main completion callback in the current task.
///
......@@ -98,25 +100,22 @@ pub fn read(prompt: &str) -> Option<~str> {
/// other than the closure that it receives as its second
/// argument. Calling such a function will deadlock on the mutex used
/// to ensure that the calls are thread-safe.
pub fn complete(cb: CompletionCb) {
pub unsafe fn complete(cb: @CompletionCb) {
local_data::set(complete_key, cb);
extern fn callback(c_line: *c_char, completions: *()) {
extern fn callback(line: *c_char, completions: *()) {
do local_data::get(complete_key) |opt_cb| {
// only fetch completions if a completion handler has been
// registered in the current task.
match opt_cb {
None => {},
None => {}
Some(cb) => {
let line = unsafe { str::raw::from_c_str(c_line) };
do (*cb)(line) |suggestion| {
do suggestion.with_c_str |buf| {
// This isn't locked, because `callback` gets
// called inside `rustrt::linenoise`, which
// *is* already inside the mutex, so
// re-locking would be a deadlock.
unsafe {
rustrt::linenoiseAddCompletion(completions, buf);
unsafe {
do cb.complete(str::raw::from_c_str(line))
|suggestion| {
do suggestion.with_c_str |buf| {
rustrt::linenoiseAddCompletion(completions,
buf);
}
}
}
......
......@@ -807,11 +807,6 @@ fn lteq(t1: &TestDescAndFn, t2: &TestDescAndFn) -> bool {
}
}
struct TestFuture {
test: TestDesc,
wait: @fn() -> TestResult,
}
pub fn run_test(force_ignore: bool,
test: TestDescAndFn,
monitor_ch: SharedChan<MonitorMsg>) {
......
......@@ -218,14 +218,25 @@ fn check_for_bare(cx: Context, fv: @freevar_entry) {
let fty = ty::node_id_to_type(cx.tcx, id);
match ty::get(fty).sty {
ty::ty_closure(ty::ClosureTy {sigil: OwnedSigil, bounds: bounds, _}) => {
ty::ty_closure(ty::ClosureTy {
sigil: OwnedSigil,
bounds: bounds,
_
}) => {
b(|cx, fv| check_for_uniq(cx, fv, bounds))
}
ty::ty_closure(ty::ClosureTy {sigil: ManagedSigil, bounds: bounds, _}) => {
b(|cx, fv| check_for_box(cx, fv, bounds))
ty::ty_closure(ty::ClosureTy {
sigil: ManagedSigil,
_
}) => {
// can't happen
}
ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, bounds: bounds,
region: region, _}) => {
ty::ty_closure(ty::ClosureTy {
sigil: BorrowedSigil,
bounds: bounds,
region: region,
_
}) => {
b(|cx, fv| check_for_block(cx, fv, bounds, region))
}
ty::ty_bare_fn(_) => {
......
......@@ -187,8 +187,7 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
Some(deref_ptr(gc_ptr(m)))
}
ty::ty_estr(ty::vstore_box) |
ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
ty::ty_estr(ty::vstore_box) => {
Some(deref_ptr(gc_ptr(ast::MutImmutable)))
}
......@@ -515,7 +514,8 @@ pub fn cat_def(&self,
(ast::BorrowedSigil, ast::Once) => true,
// Heap closures always capture by copy/move, and can
// move out iff they are once.
(ast::OwnedSigil, _) | (ast::ManagedSigil, _) => false,
(ast::OwnedSigil, _) |
(ast::ManagedSigil, _) => false,
};
if var_is_refd {
......
......@@ -116,8 +116,7 @@ fn stack_check_fn<'a>(v: StackCheckVisitor,
visit::fk_anon(*) | visit::fk_fn_block => {
match ty::get(ty::node_id_to_type(in_cx.tcx, id)).sty {
ty::ty_bare_fn(*) |
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) |
ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
false
}
_ => {
......
......@@ -172,7 +172,7 @@ pub fn allocate_cbox(bcx: @mut Block, sigil: ast::Sigil, cdata_ty: ty::t)
// Allocate and initialize the box:
match sigil {
ast::ManagedSigil => {
malloc_raw(bcx, cdata_ty, heap_managed)
tcx.sess.bug("trying to trans allocation of @fn")
}
ast::OwnedSigil => {
malloc_raw(bcx, cdata_ty, heap_for_unique_closure(bcx, cdata_ty))
......@@ -197,7 +197,8 @@ pub struct ClosureResult {
// Otherwise, it is stack allocated and copies pointers to the upvars.
pub fn store_environment(bcx: @mut Block,
bound_values: ~[EnvValue],
sigil: ast::Sigil) -> ClosureResult {
sigil: ast::Sigil)
-> ClosureResult {
let _icx = push_ctxt("closure::store_environment");
let ccx = bcx.ccx();
let tcx = ccx.tcx;
......@@ -444,27 +445,6 @@ pub fn make_closure_glue(
}
}
pub fn make_opaque_cbox_take_glue(
bcx: @mut Block,
sigil: ast::Sigil,
cboxptr: ValueRef) // ptr to ptr to the opaque closure
-> @mut Block {
// Easy cases:
let _icx = push_ctxt("closure::make_opaque_cbox_take_glue");
match sigil {
ast::BorrowedSigil => {
return bcx;
}
ast::ManagedSigil => {
glue::incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr));
return bcx;
}
ast::OwnedSigil => {
fail!("unique closures are not copyable")
}
}
}
pub fn make_opaque_cbox_drop_glue(
bcx: @mut Block,
sigil: ast::Sigil,
......@@ -474,9 +454,7 @@ pub fn make_opaque_cbox_drop_glue(
match sigil {
ast::BorrowedSigil => bcx,
ast::ManagedSigil => {
glue::decr_refcnt_maybe_free(
bcx, Load(bcx, cboxptr), Some(cboxptr),
ty::mk_opaque_closure_ptr(bcx.tcx(), sigil))
bcx.tcx().sess.bug("trying to trans drop glue of @fn")
}
ast::OwnedSigil => {
glue::free_ty(
......@@ -516,12 +494,8 @@ pub fn make_opaque_cbox_free_glue(
abi::tydesc_field_drop_glue, None);
// Free the ty descr (if necc) and the box itself
match sigil {
ast::ManagedSigil => glue::trans_free(bcx, cbox),
ast::OwnedSigil => glue::trans_exchange_free(bcx, cbox),
ast::BorrowedSigil => {
bcx.sess().bug("impossible")
}
}
glue::trans_exchange_free(bcx, cbox);
bcx
}
}
......@@ -581,11 +581,7 @@ pub fn make_take_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
| ty::ty_estr(ty::vstore_slice(_)) => {
bcx
}
ty::ty_closure(ty::ClosureTy { sigil: ast::BorrowedSigil, _ }) |
ty::ty_closure(ty::ClosureTy { sigil: ast::ManagedSigil, _ }) => {
closure::make_closure_glue(bcx, v, t, take_ty)
}
ty::ty_closure(ty::ClosureTy { sigil: ast::OwnedSigil, _ }) => bcx,
ty::ty_closure(_) => bcx,
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
let llbox = Load(bcx, GEPi(bcx, v, [0u, abi::trt_field_box]));
incr_refcnt_of_boxed(bcx, llbox);
......@@ -606,9 +602,7 @@ pub fn make_take_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
None);
bcx
}
ty::ty_opaque_closure_ptr(ck) => {
closure::make_opaque_cbox_take_glue(bcx, ck, v)
}
ty::ty_opaque_closure_ptr(_) => bcx,
ty::ty_struct(did, _) => {
let tcx = bcx.tcx();
let bcx = iter_structural_ty(bcx, v, t, take_ty);
......
......@@ -2308,12 +2308,7 @@ fn closure_contents(cty: &ClosureTy) -> TypeContents {
ast::Many => TC_NONE
};
// Prevent noncopyable types captured in the environment from being copied.
let ct = if cty.sigil == ast::ManagedSigil {
TC_NONE
} else {
TC_NONCOPY_TRAIT
};
st + rt + ot + ct
st + rt + ot + TC_NONCOPY_TRAIT
}
fn trait_contents(store: TraitStore, mutbl: ast::Mutability,
......
......@@ -400,6 +400,11 @@ fn check_path_args(tcx: ty::ctxt,
bf.abis, &bf.lifetimes, &bf.decl))
}
ast::ty_closure(ref f) => {
if f.sigil == ast::ManagedSigil {
tcx.sess.span_err(ast_ty.span,
"managed closures are not supported");
}
let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, match f.sigil {
// Use corresponding trait store to figure out default bounds
// if none were specified.
......
......@@ -403,7 +403,7 @@ struct ViewItemVisitor<'self> {
sess: session::Session,
exec: &'self mut workcache::Exec,
c: &'self ast::Crate,
save: @fn(Path),
save: &'self fn(Path),
}
impl<'self> Visitor<()> for ViewItemVisitor<'self> {
......@@ -508,7 +508,7 @@ pub fn find_and_install_dependencies(context: &BuildContext,
sess: session::Session,
exec: &mut workcache::Exec,
c: &ast::Crate,
save: @fn(Path)) {
save: &fn(Path)) {
debug!("In find_and_install_dependencies...");
let mut visitor = ViewItemVisitor {
context: context,
......
......@@ -1846,31 +1846,38 @@ fn drop(&mut self) {
pub struct Arg<t> {
val: t,
opt_level: Option<Level>,
fsync_fn: @fn(f: &t, Level) -> int,
fsync_fn: extern "Rust" fn(f: &t, Level) -> int,
}
// fsync file after executing blk
// FIXME (#2004) find better way to create resources within lifetime of
// outer res
pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
pub fn FILE_res_sync(file: &FILERes,
opt_level: Option<Level>,
blk: &fn(v: Res<*libc::FILE>)) {
blk(Res::new(Arg {
val: file.f, opt_level: opt_level,
fsync_fn: |file, l| fsync_fd(fileno(*file), l)
val: file.f,
opt_level: opt_level,
fsync_fn: fsync_FILE,
}));
fn fileno(stream: *libc::FILE) -> libc::c_int {
#[fixed_stack_segment]; #[inline(never)];
unsafe { libc::fileno(stream) }
}
fn fsync_FILE(stream: &*libc::FILE, level: Level) -> int {
fsync_fd(fileno(*stream), level)
}
}
// fsync fd after executing blk
pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
blk: &fn(v: Res<fd_t>)) {
blk(Res::new(Arg {
val: fd.fd, opt_level: opt_level,
fsync_fn: |fd, l| fsync_fd(*fd, l)
val: fd.fd,
opt_level: opt_level,
fsync_fn: fsync_fd_helper,
}));
}
......@@ -1880,6 +1887,10 @@ fn fsync_fd(fd: libc::c_int, level: Level) -> int {
os::fsync_fd(fd, level) as int
}
fn fsync_fd_helper(fd_ptr: &libc::c_int, level: Level) -> int {
fsync_fd(*fd_ptr, level)
}
// Type of objects that may want to fsync
pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
......@@ -1887,10 +1898,15 @@ fn fsync_fd(fd: libc::c_int, level: Level) -> int {
pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
blk: &fn(v: Res<@FSyncable>)) {
blk(Res::new(Arg {
val: o, opt_level: opt_level,
fsync_fn: |o, l| (*o).fsync(l)
val: o,
opt_level: opt_level,
fsync_fn: obj_fsync_fn,
}));
}
fn obj_fsync_fn(o: &@FSyncable, level: Level) -> int {
(*o).fsync(level)
}
}
#[cfg(test)]
......
......@@ -485,9 +485,11 @@ fn visit_opaque_box(&mut self) -> bool {
}
fn visit_closure_ptr(&mut self, ck: uint) -> bool {
self.align_to::<@fn()>();
if ! self.inner.visit_closure_ptr(ck) { return false; }
self.bump_past::<@fn()>();
self.align_to::<~fn()>();
if ! self.inner.visit_closure_ptr(ck) {
return false
}
self.bump_past::<~fn()>();
true
}
}
......@@ -55,7 +55,6 @@ fn finally(&self, dtor: &fn()) -> T {
}
finally_fn!(~fn() -> T)
finally_fn!(@fn() -> T)
finally_fn!(extern "Rust" fn() -> T)
struct Finallyalizer<'self> {
......
......@@ -2265,17 +2265,6 @@ pub fn print_fn_header_info(s: @ps,
print_opt_sigil(s, opt_sigil);
}
pub fn opt_sigil_to_str(opt_p: Option<ast::Sigil>) -> &'static str {
match opt_p {
None => "fn",
Some(p) => match p {
ast::BorrowedSigil => "fn&",
ast::OwnedSigil => "fn~",
ast::ManagedSigil => "fn@"
}
}
}
pub fn purity_to_str(p: ast::purity) -> &'static str {
match p {
ast::impure_fn => "impure",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册