librustc: Remove `@fn` managed closures from the language.
This commit is contained in:
parent
9a4de3f305
commit
68ea9aed96
|
@ -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 @@ local_data_key!(complete_key: CompletionCb)
|
|||
/// 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 @@ pub fn filter_tests(
|
|||
}
|
||||
}
|
||||
|
||||
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 with_appropriate_checker(cx: Context, id: NodeId,
|
|||
|
||||
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 @@ impl mem_categorization_ctxt {
|
|||
(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 @@ pub fn type_contents(cx: ctxt, ty: t) -> 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 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope + Clone + 'static>(
|
|||
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 @@ pub mod fsync {
|
|||
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 @@ pub mod fsync {
|
|||
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 @@ pub mod fsync {
|
|||
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 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
|
|||
}
|
||||
|
||||
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 @@ impl<'self,T> Finally<T> for &'self 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",
|
||||
|
|
Loading…
Reference in New Issue