about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-10-29 10:52:25 -0700
committerbors <bors@rust-lang.org>2013-10-29 10:52:25 -0700
commitfed48cc861fd858762c1e9b498675bfa4dee2d38 (patch)
tree01c61601be0db74a12ff9504f6eace70add85385
parent52f42f16387d0142944f376ea31c554c9caa2189 (diff)
parent7e77bf17694e31c741fe3a31c7eca5437d9cb6d5 (diff)
downloadrust-fed48cc861fd858762c1e9b498675bfa4dee2d38.tar.gz
rust-fed48cc861fd858762c1e9b498675bfa4dee2d38.zip
auto merge of #10132 : pcwalton/rust/proc, r=pcwalton
the feature gate for `once fn` if used with the `~` sigil.

r? @brson
-rw-r--r--src/compiletest/procsrv.rs6
-rw-r--r--src/librustc/front/feature_gate.rs3
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs2
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs2
-rw-r--r--src/librustc/middle/cfg/construct.rs1
-rw-r--r--src/librustc/middle/check_loop.rs2
-rw-r--r--src/librustc/middle/dataflow.rs3
-rw-r--r--src/librustc/middle/freevars.rs2
-rw-r--r--src/librustc/middle/liveness.rs9
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/middle/moves.rs3
-rw-r--r--src/librustc/middle/resolve.rs3
-rw-r--r--src/librustc/middle/trans/debuginfo.rs6
-rw-r--r--src/librustc/middle/trans/expr.rs5
-rw-r--r--src/librustc/middle/ty.rs1
-rw-r--r--src/librustc/middle/typeck/check/mod.rs10
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs5
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs2
-rw-r--r--src/librustc/util/ppaux.rs29
-rw-r--r--src/libstd/rt/io/native/process.rs16
-rw-r--r--src/libstd/run.rs4
-rw-r--r--src/libsyntax/ast.rs1
-rw-r--r--src/libsyntax/fold.rs3
-rw-r--r--src/libsyntax/parse/parser.rs57
-rw-r--r--src/libsyntax/parse/token.rs41
-rw-r--r--src/libsyntax/print/pprust.rs61
-rw-r--r--src/libsyntax/visit.rs8
-rw-r--r--src/test/run-pass/closure-reform.rs27
-rw-r--r--src/test/run-pass/core-run-destroy.rs10
29 files changed, 252 insertions, 72 deletions
diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs
index 829916117d2..f8123d7b05c 100644
--- a/src/compiletest/procsrv.rs
+++ b/src/compiletest/procsrv.rs
@@ -48,7 +48,7 @@ pub fn run(lib_path: &str,
            input: Option<~str>) -> Result {
 
     let env = env + target_env(lib_path, prog);
-    let mut proc = run::Process::new(prog, args, run::ProcessOptions {
+    let mut process = run::Process::new(prog, args, run::ProcessOptions {
         env: Some(env),
         dir: None,
         in_fd: None,
@@ -57,9 +57,9 @@ pub fn run(lib_path: &str,
     });
 
     for input in input.iter() {
-        proc.input().write(input.as_bytes());
+        process.input().write(input.as_bytes());
     }
-    let output = proc.finish_with_output();
+    let output = process.finish_with_output();
 
     Result {
         status: output.status,
diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs
index 6de94936d15..c17d6cabfed 100644
--- a/src/librustc/front/feature_gate.rs
+++ b/src/librustc/front/feature_gate.rs
@@ -132,7 +132,8 @@ impl Visitor<()> for Context {
 
     fn visit_ty(&mut self, t: &ast::Ty, _: ()) {
         match t.node {
-            ast::ty_closure(closure) if closure.onceness == ast::Once => {
+            ast::ty_closure(closure) if closure.onceness == ast::Once &&
+                    closure.sigil != ast::OwnedSigil => {
                 self.gate_feature("once_fns", t.span,
                                   "once functions are \
                                    experimental and likely to be removed");
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index b05bdaa2032..77dec4ede10 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -656,7 +656,7 @@ impl<'self> CheckLoanCtxt<'self> {
 
     fn check_move_out_from_expr(&self, expr: @ast::Expr) {
         match expr.node {
-            ast::ExprFnBlock(*) => {
+            ast::ExprFnBlock(*) | ast::ExprProc(*) => {
                 // moves due to capture clauses are checked
                 // in `check_loans_in_fn`, so that we can
                 // give a better error message
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index 36a49de8778..dd161b189da 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -307,7 +307,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
           this.pop_repeating_id(body.id);
       }
 
-      ast::ExprFnBlock(*) => {
+      ast::ExprFnBlock(*) | ast::ExprProc(*) => {
           gather_moves::gather_captures(this.bccx, this.move_data, ex);
           visit::walk_expr(this, ex, ());
       }
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index 27fbecb5979..fce318f173e 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -409,6 +409,7 @@ impl CFGBuilder {
             ast::ExprInlineAsm(*) |
             ast::ExprSelf |
             ast::ExprFnBlock(*) |
+            ast::ExprProc(*) |
             ast::ExprLit(*) |
             ast::ExprPath(*) => {
                 self.straightline(expr, pred, [])
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
index cc3511aa51f..a6aab151e5a 100644
--- a/src/librustc/middle/check_loop.rs
+++ b/src/librustc/middle/check_loop.rs
@@ -49,7 +49,7 @@ impl Visitor<Context> for CheckLoopVisitor {
               ExprLoop(ref b, _) => {
                 self.visit_block(b, Context { in_loop: true,.. cx });
               }
-              ExprFnBlock(_, ref b) => {
+              ExprFnBlock(_, ref b) | ExprProc(_, ref b) => {
                 self.visit_block(b, Context { in_loop: false, can_ret: false });
               }
               ExprBreak(_) => {
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 7ad55936b9e..299aa65897e 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -431,7 +431,8 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
         self.merge_with_entry_set(expr.id, in_out);
 
         match expr.node {
-            ast::ExprFnBlock(ref decl, ref body) => {
+            ast::ExprFnBlock(ref decl, ref body) |
+            ast::ExprProc(ref decl, ref body) => {
                 if self.dfcx.oper.walk_closures() {
                     // In the absence of once fns, we must assume that
                     // every function body will execute more than
diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs
index 9aaddab69a1..7b0bb80eb28 100644
--- a/src/librustc/middle/freevars.rs
+++ b/src/librustc/middle/freevars.rs
@@ -47,7 +47,7 @@ impl Visitor<int> for CollectFreevarsVisitor {
     fn visit_expr(&mut self, expr:@ast::Expr, depth:int) {
 
             match expr.node {
-              ast::ExprFnBlock(*) => {
+              ast::ExprFnBlock(*) | ast::ExprProc(*) => {
                 visit::walk_expr(self, expr, depth + 1)
               }
               ast::ExprPath(*) | ast::ExprSelf => {
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index e9e416124af..a370da2893a 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -485,7 +485,7 @@ fn visit_expr(v: &mut LivenessVisitor, expr: @Expr, this: @mut IrMaps) {
         }
         visit::walk_expr(v, expr, this);
       }
-      ExprFnBlock(*) => {
+      ExprFnBlock(*) | ExprProc(*) => {
         // Interesting control flow (for loops can contain labeled
         // breaks or continues)
         this.add_live_node_for_node(expr.id, ExprNode(expr.span));
@@ -1023,8 +1023,8 @@ impl Liveness {
               self.propagate_through_expr(e, succ)
           }
 
-          ExprFnBlock(_, ref blk) => {
-              debug!("{} is an expr_fn_block",
+          ExprFnBlock(_, ref blk) | ExprProc(_, ref blk) => {
+              debug!("{} is an ExprFnBlock or ExprProc",
                    expr_to_str(expr, self.tcx.sess.intr()));
 
               /*
@@ -1498,7 +1498,8 @@ fn check_expr(this: &mut Liveness, expr: @Expr) {
       ExprCast(*) | ExprUnary(*) | ExprRet(*) | ExprBreak(*) |
       ExprAgain(*) | ExprLit(_) | ExprBlock(*) |
       ExprMac(*) | ExprAddrOf(*) | ExprStruct(*) | ExprRepeat(*) |
-      ExprParen(*) | ExprFnBlock(*) | ExprPath(*) | ExprSelf(*) => {
+      ExprParen(*) | ExprFnBlock(*) | ExprProc(*) | ExprPath(*) |
+      ExprSelf(*) => {
         visit::walk_expr(this, expr, ());
       }
       ExprForLoop(*) => fail!("non-desugared expr_for_loop")
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 5e26201522c..bd2f69a1d03 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -424,7 +424,7 @@ impl mem_categorization_ctxt {
 
           ast::ExprAddrOf(*) | ast::ExprCall(*) |
           ast::ExprAssign(*) | ast::ExprAssignOp(*) |
-          ast::ExprFnBlock(*) | ast::ExprRet(*) |
+          ast::ExprFnBlock(*) | ast::ExprProc(*) | ast::ExprRet(*) |
           ast::ExprDoBody(*) | ast::ExprUnary(*) |
           ast::ExprMethodCall(*) | ast::ExprCast(*) | ast::ExprVstore(*) |
           ast::ExprVec(*) | ast::ExprTup(*) | ast::ExprIf(*) |
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 6317e3a1abc..36a47578e27 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -555,7 +555,8 @@ impl VisitContext {
                 self.use_expr(base, comp_mode);
             }
 
-            ExprFnBlock(ref decl, ref body) => {
+            ExprFnBlock(ref decl, ref body) |
+            ExprProc(ref decl, ref body) => {
                 for a in decl.inputs.iter() {
                     self.use_pat(a.pat);
                 }
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index c16c39b5a09..8c5deeb94d5 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -5043,7 +5043,8 @@ impl Resolver {
                 visit::walk_expr(self, expr, ());
             }
 
-            ExprFnBlock(ref fn_decl, ref block) => {
+            ExprFnBlock(ref fn_decl, ref block) |
+            ExprProc(ref fn_decl, ref block) => {
                 self.resolve_function(FunctionRibKind(expr.id, block.id),
                                       Some(fn_decl),
                                       NoTypeParameters,
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 2138afd2e9b..cea39c8e3d2 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -569,7 +569,8 @@ pub fn create_function_debug_context(cx: &mut CrateContext,
         }
         ast_map::node_expr(ref expr) => {
             match expr.node {
-                ast::ExprFnBlock(ref fn_decl, ref top_level_block) => {
+                ast::ExprFnBlock(ref fn_decl, ref top_level_block) |
+                ast::ExprProc(ref fn_decl, ref top_level_block) => {
                     let name = format!("fn{}", token::gensym("fn"));
                     let name = token::str_to_ident(name);
                     (name, fn_decl,
@@ -2579,7 +2580,8 @@ fn populate_scope_map(cx: &mut CrateContext,
                 }
             }
 
-            ast::ExprFnBlock(ast::fn_decl { inputs: ref inputs, _ }, ref block) => {
+            ast::ExprFnBlock(ast::fn_decl { inputs: ref inputs, _ }, ref block) |
+            ast::ExprProc(ast::fn_decl { inputs: ref inputs, _ }, ref block) => {
                 do with_new_scope(cx, block.span, scope_stack, scope_map) |cx,
                                                                            scope_stack,
                                                                            scope_map| {
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 1c856f04b06..ca1bd2d8a95 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -717,10 +717,11 @@ fn trans_rvalue_dps_unadjusted(bcx: @mut Block, expr: &ast::Expr,
         ast::ExprVec(*) | ast::ExprRepeat(*) => {
             return tvec::trans_fixed_vstore(bcx, expr, expr, dest);
         }
-        ast::ExprFnBlock(ref decl, ref body) => {
+        ast::ExprFnBlock(ref decl, ref body) |
+        ast::ExprProc(ref decl, ref body) => {
             let expr_ty = expr_ty(bcx, expr);
             let sigil = ty::ty_closure_sigil(expr_ty);
-            debug!("translating fn_block {} with type {}",
+            debug!("translating block function {} with type {}",
                    expr_to_str(expr, tcx.sess.intr()),
                    expr_ty.repr(tcx));
             return closure::trans_expr_fn(bcx, sigil, decl, body,
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 39aa6c5e396..fbfac3b7518 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -3263,6 +3263,7 @@ pub fn expr_kind(tcx: ctxt,
         ast::ExprIf(*) |
         ast::ExprMatch(*) |
         ast::ExprFnBlock(*) |
+        ast::ExprProc(*) |
         ast::ExprDoBody(*) |
         ast::ExprBlock(*) |
         ast::ExprRepeat(*) |
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index d71aa776689..ab6ed65d542 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -1408,6 +1408,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
             for (i, arg) in args.iter().enumerate() {
                 let is_block = match arg.node {
                     ast::ExprFnBlock(*) |
+                    ast::ExprProc(*) |
                     ast::ExprDoBody(*) => true,
                     _ => false
                 };
@@ -2592,6 +2593,15 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         check_expr_fn(fcx, expr, None,
                       decl, body, Vanilla, expected);
       }
+      ast::ExprProc(ref decl, ref body) => {
+        check_expr_fn(fcx,
+                      expr,
+                      Some(ast::OwnedSigil),
+                      decl,
+                      body,
+                      Vanilla,
+                      expected);
+      }
       ast::ExprDoBody(b) => {
         let expected_sty = unpack_expected(fcx,
                                            expected,
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 09fc7b5c15c..c0aa669d920 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -427,7 +427,7 @@ fn visit_expr(rcx: &mut Rcx, expr: @ast::Expr) {
             visit::walk_expr(rcx, expr, ());
         }
 
-        ast::ExprFnBlock(*) => {
+        ast::ExprFnBlock(*) | ast::ExprProc(*) => {
             check_expr_fn_block(rcx, expr);
         }
 
@@ -457,7 +457,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
                        expr: @ast::Expr) {
     let tcx = rcx.fcx.tcx();
     match expr.node {
-        ast::ExprFnBlock(_, ref body) => {
+        ast::ExprFnBlock(_, ref body) | ast::ExprProc(_, ref body) => {
             let function_type = rcx.resolve_node_type(expr.id);
             match ty::get(function_type).sty {
                 ty::ty_closure(
@@ -1027,6 +1027,7 @@ pub mod guarantor {
             ast::ExprIf(*) |
             ast::ExprMatch(*) |
             ast::ExprFnBlock(*) |
+            ast::ExprProc(*) |
             ast::ExprDoBody(*) |
             ast::ExprBlock(*) |
             ast::ExprRepeat(*) |
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index 46c7968a0a4..1d724e22de9 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -245,7 +245,7 @@ fn visit_expr(e: @ast::Expr, wbcx: &mut WbCtxt) {
     }
 
     match e.node {
-        ast::ExprFnBlock(ref decl, _) => {
+        ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => {
             for input in decl.inputs.iter() {
                 let _ = resolve_type_vars_for_node(wbcx, e.span, input.id);
             }
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index d5219ed0867..2f8c1f6f97d 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -337,7 +337,14 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
     }
     fn closure_to_str(cx: ctxt, cty: &ty::ClosureTy) -> ~str
     {
-        let mut s = cty.sigil.to_str();
+        let is_proc =
+            (cty.sigil, cty.onceness) == (ast::OwnedSigil, ast::Once);
+
+        let mut s = if is_proc {
+            ~""
+        } else {
+            cty.sigil.to_str()
+        };
 
         match (cty.sigil, cty.region) {
             (ast::ManagedSigil, ty::re_static) |
@@ -356,15 +363,19 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
             }
         };
 
-        match cty.onceness {
-            ast::Many => {}
-            ast::Once => {
-                s.push_str(cty.onceness.to_str());
-                s.push_char(' ');
-            }
-        };
+        if is_proc {
+            s.push_str("proc");
+        } else {
+            match cty.onceness {
+                ast::Many => {}
+                ast::Once => {
+                    s.push_str(cty.onceness.to_str());
+                    s.push_char(' ');
+                }
+            };
 
-        s.push_str("fn");
+            s.push_str("fn");
+        }
 
         if !cty.bounds.is_empty() {
             s.push_str(":");
diff --git a/src/libstd/rt/io/native/process.rs b/src/libstd/rt/io/native/process.rs
index 91fff6d9263..0fa454b94d0 100644
--- a/src/libstd/rt/io/native/process.rs
+++ b/src/libstd/rt/io/native/process.rs
@@ -649,23 +649,25 @@ fn waitpid(pid: pid_t) -> int {
 
         unsafe {
 
-            let proc = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
-            if proc.is_null() {
+            let process = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
+                                      FALSE,
+                                      pid as DWORD);
+            if process.is_null() {
                 fail!("failure in OpenProcess: {}", os::last_os_error());
             }
 
             loop {
                 let mut status = 0;
-                if GetExitCodeProcess(proc, &mut status) == FALSE {
-                    CloseHandle(proc);
+                if GetExitCodeProcess(process, &mut status) == FALSE {
+                    CloseHandle(process);
                     fail!("failure in GetExitCodeProcess: {}", os::last_os_error());
                 }
                 if status != STILL_ACTIVE {
-                    CloseHandle(proc);
+                    CloseHandle(process);
                     return status as int;
                 }
-                if WaitForSingleObject(proc, INFINITE) == WAIT_FAILED {
-                    CloseHandle(proc);
+                if WaitForSingleObject(process, INFINITE) == WAIT_FAILED {
+                    CloseHandle(process);
                     fail!("failure in WaitForSingleObject: {}", os::last_os_error());
                 }
             }
diff --git a/src/libstd/run.rs b/src/libstd/run.rs
index 973e866e335..9e6fdf2ba4c 100644
--- a/src/libstd/run.rs
+++ b/src/libstd/run.rs
@@ -413,7 +413,7 @@ mod tests {
         let pipe_out = os::pipe();
         let pipe_err = os::pipe();
 
-        let mut proc = run::Process::new("cat", [], run::ProcessOptions {
+        let mut process = run::Process::new("cat", [], run::ProcessOptions {
             dir: None,
             env: None,
             in_fd: Some(pipe_in.input),
@@ -430,7 +430,7 @@ mod tests {
         }
         let actual = readclose(pipe_out.input);
         readclose(pipe_err.input);
-        proc.finish();
+        process.finish();
 
         assert_eq!(~"test", actual);
     }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 3467e1aaadc..cf72455a83a 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -537,6 +537,7 @@ pub enum Expr_ {
     ExprLoop(Block, Option<Ident>),
     ExprMatch(@Expr, ~[Arm]),
     ExprFnBlock(fn_decl, Block),
+    ExprProc(fn_decl, Block),
     ExprDoBody(@Expr),
     ExprBlock(Block),
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index fddf674a846..d579e7dd2c7 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -786,6 +786,9 @@ pub fn noop_fold_expr<T:ast_fold>(e: @ast::Expr, folder: &T) -> @ast::Expr {
                 folder.fold_block(body)
             )
         }
+        ExprProc(ref decl, ref body) => {
+            ExprProc(fold_fn_decl(decl, folder), folder.fold_block(body))
+        }
         ExprBlock(ref blk) => ExprBlock(folder.fold_block(blk)),
         ExprAssign(el, er) => {
             ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 8b399266676..716fb5040f6 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -27,7 +27,7 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock};
 use ast::{ExprBreak, ExprCall, ExprCast, ExprDoBody};
 use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
 use ast::{ExprLit, ExprLogLevel, ExprLoop, ExprMac};
-use ast::{ExprMethodCall, ExprParen, ExprPath, ExprRepeat};
+use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc, ExprRepeat};
 use ast::{ExprRet, ExprSelf, ExprStruct, ExprTup, ExprUnary};
 use ast::{ExprVec, ExprVstore, ExprVstoreMutBox};
 use ast::{ExprVstoreSlice, ExprVstoreBox};
@@ -814,6 +814,21 @@ impl Parser {
         });
     }
 
+    // Parses a procedure type (`proc`). The initial `proc` keyword must
+    // already have been parsed.
+    pub fn parse_proc_type(&self) -> ty_ {
+        let (decl, lifetimes) = self.parse_ty_fn_decl();
+        ty_closure(@TyClosure {
+            sigil: OwnedSigil,
+            region: None,
+            purity: impure_fn,
+            onceness: Once,
+            bounds: None,
+            decl: decl,
+            lifetimes: lifetimes,
+        })
+    }
+
     // parse a ty_closure type
     pub fn parse_ty_closure(&self,
                             sigil: ast::Sigil,
@@ -1123,6 +1138,8 @@ impl Parser {
             let e = self.parse_expr();
             self.expect(&token::RPAREN);
             ty_typeof(e)
+        } else if self.eat_keyword(keywords::Proc) {
+            self.parse_proc_type()
         } else if *self.token == token::MOD_SEP
             || is_ident_or_path(self.token) {
             // NAMED TYPE
@@ -1672,6 +1689,19 @@ impl Parser {
                                  ExprBlock(blk));
         } else if token::is_bar(&*self.token) {
             return self.parse_lambda_expr();
+        } else if self.eat_keyword(keywords::Proc) {
+            let decl = self.parse_proc_decl();
+            let body = self.parse_expr();
+            let fakeblock = ast::Block {
+                view_items: ~[],
+                stmts: ~[],
+                expr: Some(body),
+                id: ast::DUMMY_NODE_ID,
+                rules: DefaultBlock,
+                span: body.span,
+            };
+
+            return self.mk_expr(lo, body.span.hi, ExprProc(decl, fakeblock));
         } else if self.eat_keyword(keywords::Self) {
             ex = ExprSelf;
             hi = self.span.hi;
@@ -3616,6 +3646,31 @@ impl Parser {
         }
     }
 
+    // Parses the `(arg, arg) -> return_type` header on a procedure.
+    fn parse_proc_decl(&self) -> fn_decl {
+        let inputs =
+            self.parse_unspanned_seq(&token::LPAREN,
+                                     &token::RPAREN,
+                                     seq_sep_trailing_allowed(token::COMMA),
+                                     |p| p.parse_fn_block_arg());
+
+        let output = if self.eat(&token::RARROW) {
+            self.parse_ty(false)
+        } else {
+            Ty {
+                id: ast::DUMMY_NODE_ID,
+                node: ty_infer,
+                span: *self.span,
+            }
+        };
+
+        ast::fn_decl {
+            inputs: inputs,
+            output: output,
+            cf: return_val,
+        }
+    }
+
     // parse the name and optional generic types of a function header.
     fn parse_fn_header(&self) -> (Ident, ast::Generics) {
         let id = self.parse_ident();
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 27747d94b66..3d8fa1b6728 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -486,14 +486,15 @@ fn mk_fresh_ident_interner() -> @ident_interner {
         "while",              // 62
         "in",                 // 63
         "continue",           // 64
-
-        "be",                 // 65
-        "pure",               // 66
-        "yield",              // 67
-        "typeof",             // 68
-        "alignof",            // 69
-        "offsetof",           // 70
-        "sizeof",             // 71
+        "proc",               // 65
+
+        "be",                 // 66
+        "pure",               // 67
+        "yield",              // 68
+        "typeof",             // 69
+        "alignof",            // 70
+        "offsetof",           // 71
+        "sizeof",             // 72
     ];
 
     @interner::StrInterner::prefill(init_vec)
@@ -502,9 +503,9 @@ fn mk_fresh_ident_interner() -> @ident_interner {
 static SELF_KEYWORD_NAME: uint = 8;
 static STATIC_KEYWORD_NAME: uint = 27;
 static STRICT_KEYWORD_START: uint = 32;
-static STRICT_KEYWORD_FINAL: uint = 64;
-static RESERVED_KEYWORD_START: uint = 65;
-static RESERVED_KEYWORD_FINAL: uint = 71;
+static STRICT_KEYWORD_FINAL: uint = 65;
+static RESERVED_KEYWORD_START: uint = 66;
+static RESERVED_KEYWORD_FINAL: uint = 72;
 
 // if an interner exists in TLS, return it. Otherwise, prepare a
 // fresh one.
@@ -645,6 +646,7 @@ pub mod keywords {
         Use,
         While,
         Continue,
+        Proc,
 
         // Reserved keywords
         Alignof,
@@ -694,14 +696,15 @@ pub mod keywords {
                 Use => Ident { name: 61, ctxt: 0 },
                 While => Ident { name: 62, ctxt: 0 },
                 Continue => Ident { name: 64, ctxt: 0 },
-
-                Alignof => Ident { name: 69, ctxt: 0 },
-                Be => Ident { name: 65, ctxt: 0 },
-                Offsetof => Ident { name: 70, ctxt: 0 },
-                Pure => Ident { name: 66, ctxt: 0 },
-                Sizeof => Ident { name: 71, ctxt: 0 },
-                Typeof => Ident { name: 68, ctxt: 0 },
-                Yield => Ident { name: 67, ctxt: 0 },
+                Proc => Ident { name: 65, ctxt: 0 },
+
+                Alignof => Ident { name: 70, ctxt: 0 },
+                Be => Ident { name: 66, ctxt: 0 },
+                Offsetof => Ident { name: 71, ctxt: 0 },
+                Pure => Ident { name: 67, ctxt: 0 },
+                Sizeof => Ident { name: 72, ctxt: 0 },
+                Typeof => Ident { name: 69, ctxt: 0 },
+                Yield => Ident { name: 68, ctxt: 0 },
             }
         }
     }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index f3090c7dd16..33bdcdd1b03 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1350,6 +1350,33 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         // empty box to satisfy the close.
         ibox(s, 0);
       }
+      ast::ExprProc(ref decl, ref body) => {
+        // in do/for blocks we don't want to show an empty
+        // argument list, but at this point we don't know which
+        // we are inside.
+        //
+        // if !decl.inputs.is_empty() {
+        print_proc_args(s, decl);
+        space(s.s);
+        // }
+        assert!(body.stmts.is_empty());
+        assert!(body.expr.is_some());
+        // we extract the block, so as not to create another set of boxes
+        match body.expr.unwrap().node {
+            ast::ExprBlock(ref blk) => {
+                print_block_unclosed(s, blk);
+            }
+            _ => {
+                // this is a bare expression
+                print_expr(s, body.expr.unwrap());
+                end(s); // need to close a box
+            }
+        }
+        // a box will be closed by print_expr, but we didn't want an overall
+        // wrapper so we closed the corresponding opening. so create an
+        // empty box to satisfy the close.
+        ibox(s, 0);
+      }
       ast::ExprDoBody(body) => {
         print_expr(s, body);
       }
@@ -1777,6 +1804,24 @@ pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) {
     maybe_print_comment(s, decl.output.span.lo);
 }
 
+pub fn print_proc_args(s: @ps, decl: &ast::fn_decl) {
+    word(s.s, "proc");
+    word(s.s, "(");
+    print_fn_args(s, decl, None);
+    word(s.s, ")");
+
+    match decl.output.node {
+        ast::ty_infer => {}
+        _ => {
+            space_if_not_bol(s);
+            word_space(s, "->");
+            print_type(s, &decl.output);
+        }
+    }
+
+    maybe_print_comment(s, decl.output.span.lo);
+}
+
 pub fn print_bounds(s: @ps, bounds: &OptVec<ast::TyParamBound>,
                     print_colon_anyway: bool) {
     if !bounds.is_empty() {
@@ -1968,12 +2013,16 @@ pub fn print_ty_fn(s: @ps,
 
     // Duplicates the logic in `print_fn_header_info()`.  This is because that
     // function prints the sigil in the wrong place.  That should be fixed.
-    print_extern_opt_abis(s, opt_abis);
-    print_opt_sigil(s, opt_sigil);
-    print_opt_lifetime(s, opt_region);
-    print_purity(s, purity);
-    print_onceness(s, onceness);
-    word(s.s, "fn");
+    if opt_sigil == Some(ast::OwnedSigil) && onceness == ast::Once {
+        word(s.s, "proc");
+    } else {
+        print_extern_opt_abis(s, opt_abis);
+        print_opt_sigil(s, opt_sigil);
+        print_opt_lifetime(s, opt_region);
+        print_purity(s, purity);
+        print_onceness(s, onceness);
+        word(s.s, "fn");
+    }
     match id { Some(id) => { word(s.s, " "); print_ident(s, id); } _ => () }
     do opt_bounds.as_ref().map |bounds| { print_bounds(s, bounds, true); };
     match generics { Some(g) => print_generics(s, g), _ => () }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index e879d67fbf2..09ee87d1701 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -560,6 +560,14 @@ pub fn walk_expr<E:Clone, V:Visitor<E>>(visitor: &mut V, expression: @Expr, env:
                              expression.id,
                              env.clone())
         }
+        ExprProc(ref function_declaration, ref body) => {
+            visitor.visit_fn(&fk_fn_block,
+                             function_declaration,
+                             body,
+                             expression.span,
+                             expression.id,
+                             env.clone())
+        }
         ExprBlock(ref block) => visitor.visit_block(block, env.clone()),
         ExprAssign(left_hand_expression, right_hand_expression) => {
             visitor.visit_expr(right_hand_expression, env.clone());
diff --git a/src/test/run-pass/closure-reform.rs b/src/test/run-pass/closure-reform.rs
new file mode 100644
index 00000000000..c765ebe9643
--- /dev/null
+++ b/src/test/run-pass/closure-reform.rs
@@ -0,0 +1,27 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+fn call_it(f: proc(~str) -> ~str) {
+    println(f(~"Fred"))
+}
+
+pub fn main() {
+    let greeting = ~"Hi ";
+    do call_it |s| {
+        greeting + s
+    }
+
+    let greeting = ~"Hello ";
+    call_it(proc(s) {
+        greeting + s
+    });
+
+    let greeting = ~"Goodbye ";
+    call_it(proc(s) greeting + s);
+
+    let greeting = ~"How's life, ";
+    call_it(proc(s: ~str) -> ~str {
+        greeting + s
+    });
+}
+
diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs
index 4ff184b4483..aee4c7e40bc 100644
--- a/src/test/run-pass/core-run-destroy.rs
+++ b/src/test/run-pass/core-run-destroy.rs
@@ -64,14 +64,14 @@ fn test_destroy_actually_kills(force: bool) {
         use std::libc::consts::os::extra::{FALSE, PROCESS_QUERY_INFORMATION, STILL_ACTIVE };
 
         unsafe {
-            let proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
-            if proc.is_null() {
+            let process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
+            if process.is_null() {
                 return false;
             }
-            // proc will be non-null if the process is alive, or if it died recently
+            // process will be non-null if the process is alive, or if it died recently
             let mut status = 0;
-            GetExitCodeProcess(proc, &mut status);
-            CloseHandle(proc);
+            GetExitCodeProcess(process, &mut status);
+            CloseHandle(process);
             return status == STILL_ACTIVE;
         }
     }