about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/abi.rs2
-rw-r--r--src/libsyntax/ast.rs13
-rw-r--r--src/libsyntax/ast_map/mod.rs8
-rw-r--r--src/libsyntax/ast_util.rs29
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs27
-rw-r--r--src/libsyntax/ext/expand.rs10
-rw-r--r--src/libsyntax/fold.rs17
-rw-r--r--src/libsyntax/parse/parser.rs119
-rw-r--r--src/libsyntax/print/pprust.rs61
-rw-r--r--src/libsyntax/visit.rs12
10 files changed, 210 insertions, 88 deletions
diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs
index 8b01002831b..6f809383620 100644
--- a/src/libsyntax/abi.rs
+++ b/src/libsyntax/abi.rs
@@ -30,6 +30,7 @@ pub enum Abi {
     C,
     System,
     RustIntrinsic,
+    RustCall,
 }
 
 #[allow(non_camel_case_types)]
@@ -85,6 +86,7 @@ static AbiDatas: &'static [AbiData] = &[
     AbiData {abi: C, name: "C", abi_arch: AllArch},
     AbiData {abi: System, name: "system", abi_arch: AllArch},
     AbiData {abi: RustIntrinsic, name: "rust-intrinsic", abi_arch: RustArch},
+    AbiData {abi: RustCall, name: "rust-call", abi_arch: RustArch},
 ];
 
 /// Returns the ABI with the given name (if any).
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index d9f14bfa156..394d4a82516 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -503,6 +503,7 @@ pub enum Expr_ {
     ExprMatch(Gc<Expr>, Vec<Arm>),
     ExprFnBlock(P<FnDecl>, P<Block>),
     ExprProc(P<FnDecl>, P<Block>),
+    ExprUnboxedFn(P<FnDecl>, P<Block>),
     ExprBlock(P<Block>),
 
     ExprAssign(Gc<Expr>, Gc<Expr>),
@@ -690,6 +691,7 @@ pub struct TypeMethod {
     pub ident: Ident,
     pub attrs: Vec<Attribute>,
     pub fn_style: FnStyle,
+    pub abi: Abi,
     pub decl: P<FnDecl>,
     pub generics: Generics,
     pub explicit_self: ExplicitSelf,
@@ -966,13 +968,20 @@ pub struct Method {
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
     pub span: Span,
-    pub node: Method_
+    pub node: Method_,
 }
 
 #[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Method_ {
     /// Represents a method declaration
-    MethDecl(Ident, Generics, ExplicitSelf, FnStyle, P<FnDecl>, P<Block>, Visibility),
+    MethDecl(Ident,
+             Generics,
+             Abi,
+             ExplicitSelf,
+             FnStyle,
+             P<FnDecl>,
+             P<Block>,
+             Visibility),
     /// Represents a macro in method position
     MethMac(Mac),
 }
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 50e487b63db..c77f7db1c6d 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -320,13 +320,15 @@ impl Map {
             }
             NodeForeignItem(i) => PathName(i.ident.name),
             NodeMethod(m) => match m.node {
-                MethDecl(ident, _, _, _, _, _, _) => PathName(ident.name),
+                MethDecl(ident, _, _, _, _, _, _, _) => PathName(ident.name),
                 MethMac(_) => fail!("no path elem for {:?}", node)
             },
             NodeTraitMethod(tm) => match *tm {
                 Required(ref m) => PathName(m.ident.name),
                 Provided(m) => match m.node {
-                    MethDecl(ident, _, _, _, _, _, _) => PathName(ident.name),
+                    MethDecl(ident, _, _, _, _, _, _, _) => {
+                        PathName(ident.name)
+                    }
                     MethMac(_) => fail!("no path elem for {:?}", node),
                 }
             },
@@ -709,7 +711,7 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String {
             format!("foreign item {} (id={})", path_str, id)
         }
         Some(NodeMethod(m)) => match m.node {
-            MethDecl(ident, _, _, _, _, _, _) =>
+            MethDecl(ident, _, _, _, _, _, _, _) =>
                 format!("method {} in {} (id={})",
                         token::get_ident(ident),
                         map.path_to_string(id), id),
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 5431a3db16e..2b98a3bdd28 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use abi::Abi;
 use ast::*;
 use ast;
 use ast_util;
@@ -249,7 +250,14 @@ pub fn trait_method_to_ty_method(method: &TraitMethod) -> TypeMethod {
         Required(ref m) => (*m).clone(),
         Provided(m) => {
             match m.node {
-                MethDecl(ident, ref generics, explicit_self, fn_style, decl, _, vis) => {
+                MethDecl(ident,
+                         ref generics,
+                         abi,
+                         explicit_self,
+                         fn_style,
+                         decl,
+                         _,
+                         vis) => {
                     TypeMethod {
                         ident: ident,
                         attrs: m.attrs.clone(),
@@ -260,6 +268,7 @@ pub fn trait_method_to_ty_method(method: &TraitMethod) -> TypeMethod {
                         id: m.id,
                         span: m.span,
                         vis: vis,
+                        abi: abi,
                     }
                 },
                 MethMac(_) => fail!("expected non-macro method declaration")
@@ -749,6 +758,7 @@ pub fn static_has_significant_address(mutbl: ast::Mutability,
 pub trait PostExpansionMethod {
     fn pe_ident(&self) -> ast::Ident;
     fn pe_generics<'a>(&'a self) -> &'a ast::Generics;
+    fn pe_abi(&self) -> Abi;
     fn pe_explicit_self<'a>(&'a self) -> &'a ast::ExplicitSelf;
     fn pe_fn_style(&self) -> ast::FnStyle;
     fn pe_fn_decl(&self) -> P<ast::FnDecl>;
@@ -797,25 +807,28 @@ macro_rules! mf_method{
 // PRE
 impl PostExpansionMethod for Method {
     fn pe_ident(&self) -> ast::Ident {
-        mf_method_body!(self,MethDecl(ident,_,_,_,_,_,_),ident)
+        mf_method_body!(self, MethDecl(ident,_,_,_,_,_,_,_),ident)
     }
     fn pe_generics<'a>(&'a self) -> &'a ast::Generics {
-        mf_method_body!(self,MethDecl(_,ref generics,_,_,_,_,_),generics)
+        mf_method_body!(self, MethDecl(_,ref generics,_,_,_,_,_,_),generics)
+    }
+    fn pe_abi(&self) -> Abi {
+        mf_method_body!(self, MethDecl(_,_,abi,_,_,_,_,_),abi)
     }
     fn pe_explicit_self<'a>(&'a self) -> &'a ast::ExplicitSelf {
-        mf_method_body!(self,MethDecl(_,_,ref explicit_self,_,_,_,_),explicit_self)
+        mf_method_body!(self, MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self)
     }
     fn pe_fn_style(&self) -> ast::FnStyle{
-        mf_method_body!(self,MethDecl(_,_,_,fn_style,_,_,_),fn_style)
+        mf_method_body!(self, MethDecl(_,_,_,_,fn_style,_,_,_),fn_style)
     }
     fn pe_fn_decl(&self) -> P<ast::FnDecl> {
-        mf_method_body!(self,MethDecl(_,_,_,_,decl,_,_),decl)
+        mf_method_body!(self, MethDecl(_,_,_,_,_,decl,_,_),decl)
     }
     fn pe_body(&self) -> P<ast::Block> {
-        mf_method_body!(self,MethDecl(_,_,_,_,_,body,_),body)
+        mf_method_body!(self, MethDecl(_,_,_,_,_,_,body,_),body)
     }
     fn pe_vis(&self) -> ast::Visibility {
-        mf_method_body!(self,MethDecl(_,_,_,_,_,_,vis),vis)
+        mf_method_body!(self, MethDecl(_,_,_,_,_,_,_,vis),vis)
     }
 }
 
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index f1c1784146a..871f277a2da 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -183,6 +183,8 @@
 use std::cell::RefCell;
 use std::gc::{Gc, GC};
 
+use abi::Abi;
+use abi;
 use ast;
 use ast::{P, EnumDef, Expr, Ident, Generics, StructDef};
 use ast_util;
@@ -477,9 +479,13 @@ impl<'a> TraitDef<'a> {
                                                      nonself_args.as_slice())
             };
 
-            method_def.create_method(cx, self,
-                                     type_ident, generics,
-                                     explicit_self, tys,
+            method_def.create_method(cx,
+                                     self,
+                                     type_ident,
+                                     generics,
+                                     abi::Rust,
+                                     explicit_self,
+                                     tys,
                                      body)
         }).collect();
 
@@ -513,9 +519,13 @@ impl<'a> TraitDef<'a> {
                                                    nonself_args.as_slice())
             };
 
-            method_def.create_method(cx, self,
-                                     type_ident, generics,
-                                     explicit_self, tys,
+            method_def.create_method(cx,
+                                     self,
+                                     type_ident,
+                                     generics,
+                                     abi::Rust,
+                                     explicit_self,
+                                     tys,
                                      body)
         }).collect();
 
@@ -622,9 +632,11 @@ impl<'a> MethodDef<'a> {
                      trait_: &TraitDef,
                      type_ident: Ident,
                      generics: &Generics,
+                     abi: Abi,
                      explicit_self: ast::ExplicitSelf,
                      arg_types: Vec<(Ident, P<ast::Ty>)> ,
-                     body: Gc<Expr>) -> Gc<ast::Method> {
+                     body: Gc<Expr>)
+                     -> Gc<ast::Method> {
         // create the generics that aren't for Self
         let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
 
@@ -653,6 +665,7 @@ impl<'a> MethodDef<'a> {
             span: trait_.span,
             node: ast::MethDecl(method_ident,
                                 fn_generics,
+                                abi,
                                 explicit_self,
                                 ast::NormalFn,
                                 fn_decl,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 1cbe863e4e4..fdb698441fc 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -910,7 +910,14 @@ impl<'a> Folder for PatIdentRenamer<'a> {
 fn expand_method(m: &ast::Method, fld: &mut MacroExpander) -> SmallVector<Gc<ast::Method>> {
     let id = fld.new_id(m.id);
     match m.node {
-        ast::MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => {
+        ast::MethDecl(ident,
+                      ref generics,
+                      abi,
+                      ref explicit_self,
+                      fn_style,
+                      decl,
+                      body,
+                      vis) => {
             let (rewritten_fn_decl, rewritten_body)
                 = expand_and_rename_fn_decl_and_block(&*decl,body,fld);
             SmallVector::one(box(GC) ast::Method {
@@ -919,6 +926,7 @@ fn expand_method(m: &ast::Method, fld: &mut MacroExpander) -> SmallVector<Gc<ast
                     span: fld.new_span(m.span),
                     node: ast::MethDecl(fld.fold_ident(ident),
                                         fold_generics(generics, fld),
+                                        abi,
                                         fld.fold_explicit_self(explicit_self),
                                         fn_style,
                                         rewritten_fn_decl,
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 5467afab9f5..5417991c9df 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -727,6 +727,7 @@ pub fn noop_fold_type_method<T: Folder>(m: &TypeMethod, fld: &mut T) -> TypeMeth
         ident: fld.fold_ident(m.ident),
         attrs: m.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(),
         fn_style: m.fn_style,
+        abi: m.abi,
         decl: fld.fold_fn_decl(&*m.decl),
         generics: fold_generics(&m.generics, fld),
         explicit_self: fld.fold_explicit_self(&m.explicit_self),
@@ -818,9 +819,17 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> SmallVector<Gc
         id: id,
         span: folder.new_span(m.span),
         node: match m.node {
-            MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => {
+            MethDecl(ident,
+                     ref generics,
+                     abi,
+                     ref explicit_self,
+                     fn_style,
+                     decl,
+                     body,
+                     vis) => {
                 MethDecl(folder.fold_ident(ident),
                          fold_generics(generics, folder),
+                         abi,
                          folder.fold_explicit_self(explicit_self),
                          fn_style,
                          folder.fold_fn_decl(&*decl),
@@ -948,7 +957,11 @@ pub fn noop_fold_expr<T: Folder>(e: Gc<Expr>, folder: &mut T) -> Gc<Expr> {
             ExprProc(folder.fold_fn_decl(&**decl),
                      folder.fold_block(body.clone()))
         }
-        ExprBlock(ref blk) => ExprBlock(folder.fold_block(blk.clone())),
+        ExprUnboxedFn(ref decl, ref body) => {
+            ExprUnboxedFn(folder.fold_fn_decl(&**decl),
+                          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 a77f24f98f8..394288bd9f2 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -25,7 +25,7 @@ use ast::{ExprBreak, ExprCall, ExprCast};
 use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
 use ast::{ExprLit, ExprLoop, ExprMac};
 use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
-use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
+use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn};
 use ast::{ExprVec, ExprVstore, ExprVstoreSlice};
 use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, Field, FnDecl};
 use ast::{ExprVstoreUniq, Once, Many};
@@ -59,6 +59,7 @@ use ast::Visibility;
 use ast;
 use ast_util::{as_prec, ident_to_path, lit_is_str, operator_prec};
 use ast_util;
+use attr;
 use codemap::{Span, BytePos, Spanned, spanned, mk_sp};
 use codemap;
 use parse;
@@ -1217,6 +1218,16 @@ impl<'a> Parser<'a> {
             // NB: at the moment, trait methods are public by default; this
             // could change.
             let vis = p.parse_visibility();
+            let abi = if p.eat_keyword(keywords::Extern) {
+                p.parse_opt_abi().unwrap_or(abi::C)
+            } else if attr::contains_name(attrs.as_slice(),
+                                          "rust_call_abi_hack") {
+                // FIXME(stage0, pcwalton): Remove this awful hack after a
+                // snapshot, and change to `extern "rust-call" fn`.
+                abi::RustCall
+            } else {
+                abi::Rust
+            };
             let style = p.parse_fn_style();
             let ident = p.parse_ident();
 
@@ -1239,6 +1250,7 @@ impl<'a> Parser<'a> {
                     fn_style: style,
                     decl: d,
                     generics: generics,
+                    abi: abi,
                     explicit_self: explicit_self,
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, hi),
@@ -1254,7 +1266,14 @@ impl<'a> Parser<'a> {
                     attrs: attrs,
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, hi),
-                    node: ast::MethDecl(ident, generics, explicit_self, style, d, body, vis)
+                    node: ast::MethDecl(ident,
+                                        generics,
+                                        abi,
+                                        explicit_self,
+                                        style,
+                                        d,
+                                        body,
+                                        vis)
                 })
               }
 
@@ -2620,51 +2639,11 @@ impl<'a> Parser<'a> {
         self.mk_expr(lo, hi, ExprIf(cond, thn, els))
     }
 
-    /// `|args| { ... }` or `{ ...}` like in `do` expressions
-    pub fn parse_lambda_block_expr(&mut self) -> Gc<Expr> {
-        self.parse_lambda_expr_(
-            |p| {
-                match p.token {
-                    token::BINOP(token::OR) | token::OROR => {
-                        p.parse_fn_block_decl()
-                    }
-                    _ => {
-                        // No argument list - `do foo {`
-                        P(FnDecl {
-                            inputs: Vec::new(),
-                            output: P(Ty {
-                                id: ast::DUMMY_NODE_ID,
-                                node: TyInfer,
-                                span: p.span
-                            }),
-                            cf: Return,
-                            variadic: false
-                        })
-                    }
-                }
-            },
-            |p| {
-                let blk = p.parse_block();
-                p.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk))
-            })
-    }
-
-    /// `|args| expr`
+    // `|args| expr`
     pub fn parse_lambda_expr(&mut self) -> Gc<Expr> {
-        self.parse_lambda_expr_(|p| p.parse_fn_block_decl(),
-                                |p| p.parse_expr())
-    }
-
-    /// parse something of the form |args| expr
-    /// this is used both in parsing a lambda expr
-    /// and in parsing a block expr as e.g. in for...
-    pub fn parse_lambda_expr_(&mut self,
-                              parse_decl: |&mut Parser| -> P<FnDecl>,
-                              parse_body: |&mut Parser| -> Gc<Expr>)
-                              -> Gc<Expr> {
         let lo = self.span.lo;
-        let decl = parse_decl(self);
-        let body = parse_body(self);
+        let (decl, is_unboxed) = self.parse_fn_block_decl();
+        let body = self.parse_expr();
         let fakeblock = P(ast::Block {
             view_items: Vec::new(),
             stmts: Vec::new(),
@@ -2674,7 +2653,11 @@ impl<'a> Parser<'a> {
             span: body.span,
         });
 
-        return self.mk_expr(lo, body.span.hi, ExprFnBlock(decl, fakeblock));
+        if is_unboxed {
+            self.mk_expr(lo, body.span.hi, ExprUnboxedFn(decl, fakeblock))
+        } else {
+            self.mk_expr(lo, body.span.hi, ExprFnBlock(decl, fakeblock))
+        }
     }
 
     pub fn parse_else_expr(&mut self) -> Gc<Expr> {
@@ -3955,18 +3938,30 @@ impl<'a> Parser<'a> {
         (spanned(lo, hi, explicit_self), fn_decl)
     }
 
-    /// Parse the |arg, arg| header on a lambda
-    fn parse_fn_block_decl(&mut self) -> P<FnDecl> {
-        let inputs_captures = {
+    // parse the |arg, arg| header on a lambda
+    fn parse_fn_block_decl(&mut self) -> (P<FnDecl>, bool) {
+        let (is_unboxed, inputs_captures) = {
             if self.eat(&token::OROR) {
-                Vec::new()
+                (false, Vec::new())
             } else {
-                self.parse_unspanned_seq(
-                    &token::BINOP(token::OR),
+                self.expect(&token::BINOP(token::OR));
+                let is_unboxed = self.token == token::BINOP(token::AND) &&
+                    self.look_ahead(1, |t| {
+                        token::is_keyword(keywords::Mut, t)
+                    }) &&
+                    self.look_ahead(2, |t| *t == token::COLON);
+                if is_unboxed {
+                    self.bump();
+                    self.bump();
+                    self.bump();
+                }
+                let args = self.parse_seq_to_before_end(
                     &token::BINOP(token::OR),
                     seq_sep_trailing_disallowed(token::COMMA),
                     |p| p.parse_fn_block_arg()
-                )
+                );
+                self.bump();
+                (is_unboxed, args)
             }
         };
         let output = if self.eat(&token::RARROW) {
@@ -3979,12 +3974,12 @@ impl<'a> Parser<'a> {
             })
         };
 
-        P(FnDecl {
+        (P(FnDecl {
             inputs: inputs_captures,
             output: output,
             cf: Return,
             variadic: false
-        })
+        }), is_unboxed)
     }
 
     /// Parses the `(arg, arg) -> return_type` header on a procedure.
@@ -4079,6 +4074,11 @@ impl<'a> Parser<'a> {
                 (ast::MethMac(m), self.span.hi, attrs)
             } else {
                 let visa = self.parse_visibility();
+                let abi = if self.eat_keyword(keywords::Extern) {
+                    self.parse_opt_abi().unwrap_or(abi::C)
+                } else {
+                    abi::Rust
+                };
                 let fn_style = self.parse_fn_style();
                 let ident = self.parse_ident();
                 let generics = self.parse_generics();
@@ -4087,7 +4087,14 @@ impl<'a> Parser<'a> {
                     });
                 let (inner_attrs, body) = self.parse_inner_attrs_and_block();
                 let new_attrs = attrs.append(inner_attrs.as_slice());
-                (ast::MethDecl(ident, generics, explicit_self, fn_style, decl, body, visa),
+                (ast::MethDecl(ident,
+                               generics,
+                               abi,
+                               explicit_self,
+                               fn_style,
+                               decl,
+                               body,
+                               visa),
                  body.span.hi, new_attrs)
             }
         };
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 10caaea86cf..dd96118ea49 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -188,7 +188,7 @@ pub fn method_to_string(p: &ast::Method) -> String {
 }
 
 pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
-    to_string(|s| s.print_fn_block_args(p))
+    to_string(|s| s.print_fn_block_args(p, false))
 }
 
 pub fn path_to_string(p: &ast::Path) -> String {
@@ -259,7 +259,8 @@ fn needs_parentheses(expr: &ast::Expr) -> bool {
     match expr.node {
         ast::ExprAssign(..) | ast::ExprBinary(..) |
         ast::ExprFnBlock(..) | ast::ExprProc(..) |
-        ast::ExprAssignOp(..) | ast::ExprCast(..) => true,
+        ast::ExprUnboxedFn(..) | ast::ExprAssignOp(..) |
+        ast::ExprCast(..) => true,
         _ => false,
     }
 }
@@ -1004,9 +1005,20 @@ impl<'a> State<'a> {
         try!(self.maybe_print_comment(meth.span.lo));
         try!(self.print_outer_attributes(meth.attrs.as_slice()));
         match meth.node {
-            ast::MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => {
-                try!(self.print_fn(&*decl, Some(fn_style), abi::Rust,
-                                   ident, generics, Some(explicit_self.node),
+            ast::MethDecl(ident,
+                          ref generics,
+                          abi,
+                          ref explicit_self,
+                          fn_style,
+                          decl,
+                          body,
+                          vis) => {
+                try!(self.print_fn(&*decl,
+                                   Some(fn_style),
+                                   abi,
+                                   ident,
+                                   generics,
+                                   Some(explicit_self.node),
                                    vis));
                 try!(word(&mut self.s, " "));
                 self.print_block_with_attrs(&*body, meth.attrs.as_slice())
@@ -1446,7 +1458,37 @@ impl<'a> State<'a> {
                 // we are inside.
                 //
                 // if !decl.inputs.is_empty() {
-                try!(self.print_fn_block_args(&**decl));
+                try!(self.print_fn_block_args(&**decl, false));
+                try!(space(&mut self.s));
+                // }
+
+                if !body.stmts.is_empty() || !body.expr.is_some() {
+                    try!(self.print_block_unclosed(&**body));
+                } else {
+                    // we extract the block, so as not to create another set of boxes
+                    match body.expr.unwrap().node {
+                        ast::ExprBlock(blk) => {
+                            try!(self.print_block_unclosed(&*blk));
+                        }
+                        _ => {
+                            // this is a bare expression
+                            try!(self.print_expr(&*body.expr.unwrap()));
+                            try!(self.end()); // 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.
+                try!(self.ibox(0));
+            }
+            ast::ExprUnboxedFn(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() {
+                try!(self.print_fn_block_args(&**decl, true));
                 try!(space(&mut self.s));
                 // }
 
@@ -1939,8 +1981,13 @@ impl<'a> State<'a> {
     }
 
     pub fn print_fn_block_args(&mut self,
-                               decl: &ast::FnDecl) -> IoResult<()> {
+                               decl: &ast::FnDecl,
+                               is_unboxed: bool)
+                               -> IoResult<()> {
         try!(word(&mut self.s, "|"));
+        if is_unboxed {
+            try!(self.word_space("&mut:"));
+        }
         try!(self.print_fn_args(decl, None));
         try!(word(&mut self.s, "|"));
 
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index cd953607ea2..d5fb75a4d69 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -562,7 +562,7 @@ pub fn walk_method_helper<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                    method: &Method,
                                                    env: E) {
     match method.node {
-        MethDecl(ident, ref generics, _, _, decl, body, _) => {
+        MethDecl(ident, ref generics, _, _, _, decl, body, _) => {
             visitor.visit_ident(method.span, ident, env.clone());
             visitor.visit_fn(&FkMethod(ident, generics, method),
                              &*decl,
@@ -594,7 +594,7 @@ pub fn walk_fn<E: Clone, V: Visitor<E>>(visitor: &mut V,
         FkMethod(_, generics, method) => {
             visitor.visit_generics(generics, env.clone());
             match method.node {
-                MethDecl(_, _, ref explicit_self, _, _, _, _) =>
+                MethDecl(_, _, _, ref explicit_self, _, _, _, _) =>
                     visitor.visit_explicit_self(explicit_self, env.clone()),
                 MethMac(ref mac) =>
                     visitor.visit_mac(mac, env.clone())
@@ -790,6 +790,14 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
                              expression.id,
                              env.clone())
         }
+        ExprUnboxedFn(ref function_declaration, ref body) => {
+            visitor.visit_fn(&FkFnBlock,
+                             &**function_declaration,
+                             &**body,
+                             expression.span,
+                             expression.id,
+                             env.clone())
+        }
         ExprProc(ref function_declaration, ref body) => {
             visitor.visit_fn(&FkFnBlock,
                              &**function_declaration,