about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/intravisit.rs11
-rw-r--r--src/librustc/hir/lowering.rs26
-rw-r--r--src/librustc/hir/map/blocks.rs39
-rw-r--r--src/librustc/hir/map/mod.rs2
-rw-r--r--src/librustc/hir/mod.rs35
-rw-r--r--src/librustc/hir/print.rs45
-rw-r--r--src/librustc/ich/impls_hir.rs17
-rw-r--r--src/librustc/middle/reachable.rs4
-rw-r--r--src/librustc/middle/resolve_lifetime.rs2
-rw-r--r--src/librustc_allocator/expand.rs12
-rw-r--r--src/librustc_driver/pretty.rs12
-rw-r--r--src/librustc_lint/bad_style.rs4
-rw-r--r--src/librustc_lint/builtin.rs6
-rw-r--r--src/librustc_metadata/encoder.rs12
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs4
-rw-r--r--src/librustc_passes/ast_validation.rs4
-rw-r--r--src/librustc_save_analysis/sig.rs24
-rw-r--r--src/librustc_typeck/collect.rs10
-rw-r--r--src/librustdoc/clean/inline.rs9
-rw-r--r--src/librustdoc/clean/mod.rs48
-rw-r--r--src/librustdoc/doctree.rs5
-rw-r--r--src/librustdoc/html/render.rs37
-rw-r--r--src/librustdoc/visit_ast.rs14
-rw-r--r--src/libsyntax/ast.rs37
-rw-r--r--src/libsyntax/ext/build.rs9
-rw-r--r--src/libsyntax/feature_gate.rs41
-rw-r--r--src/libsyntax/fold.rs8
-rw-r--r--src/libsyntax/parse/mod.rs13
-rw-r--r--src/libsyntax/parse/parser.rs50
-rw-r--r--src/libsyntax/print/pprust.rs47
-rw-r--r--src/libsyntax/test.rs46
-rw-r--r--src/libsyntax/visit.rs12
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs10
33 files changed, 367 insertions, 288 deletions
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index ed86ef70564..766909f5723 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -41,7 +41,6 @@
 //! This order consistency is required in a few places in rustc, for
 //! example generator inference, and possibly also HIR borrowck.
 
-use rustc_target::spec::abi::Abi;
 use syntax::ast::{NodeId, CRATE_NODE_ID, Ident, Name, Attribute};
 use syntax_pos::Span;
 use hir::*;
@@ -54,8 +53,8 @@ use std::u32;
 
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum FnKind<'a> {
-    /// fn foo() or extern "Abi" fn foo()
-    ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, &'a Visibility, &'a [Attribute]),
+    /// #[xxx] pub async/const/extern "Abi" fn foo()
+    ItemFn(Name, &'a Generics, FnHeader, &'a Visibility, &'a [Attribute]),
 
     /// fn foo(&self)
     Method(Name, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]),
@@ -479,12 +478,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_ty(typ);
             visitor.visit_nested_body(body);
         }
-        ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => {
+        ItemFn(ref declaration, header, ref generics, body_id) => {
             visitor.visit_fn(FnKind::ItemFn(item.name,
                                             generics,
-                                            unsafety,
-                                            constness,
-                                            abi,
+                                            header,
                                             &item.vis,
                                             &item.attrs),
                              declaration,
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 6291e0eb113..16405b602be 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2284,7 +2284,7 @@ impl<'a> LoweringContext<'a> {
                 let value = self.lower_body(None, |this| this.lower_expr(e));
                 hir::ItemConst(self.lower_ty(t, ImplTraitContext::Disallowed), value)
             }
-            ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
+            ItemKind::Fn(ref decl, header, ref generics, ref body) => {
                 let fn_def_id = self.resolver.definitions().local_def_id(id);
                 self.with_new_scopes(|this| {
                     let body_id = this.lower_body(Some(decl), |this| {
@@ -2300,9 +2300,7 @@ impl<'a> LoweringContext<'a> {
 
                     hir::ItemFn(
                         fn_decl,
-                        this.lower_unsafety(unsafety),
-                        this.lower_constness(constness),
-                        abi,
+                        this.lower_fn_header(header),
                         generics,
                         body_id,
                     )
@@ -2891,9 +2889,7 @@ impl<'a> LoweringContext<'a> {
         impl_trait_return_allow: bool,
     ) -> hir::MethodSig {
         hir::MethodSig {
-            abi: sig.abi,
-            unsafety: self.lower_unsafety(sig.unsafety),
-            constness: self.lower_constness(sig.constness),
+            header: self.lower_fn_header(sig.header),
             decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow),
         }
     }
@@ -2905,6 +2901,15 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
+    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+        hir::FnHeader {
+            unsafety: self.lower_unsafety(h.unsafety),
+            asyncness: self.lower_asyncness(h.asyncness),
+            constness: self.lower_constness(h.constness),
+            abi: h.abi,
+        }
+    }
+
     fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
         match u {
             Unsafety::Unsafe => hir::Unsafety::Unsafe,
@@ -2919,6 +2924,13 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
+    fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
+        match a {
+            IsAsync::Async => hir::IsAsync::Async,
+            IsAsync::NotAsync => hir::IsAsync::NotAsync,
+        }
+    }
+
     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
         match u {
             UnOp::Deref => hir::UnDeref,
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 362c0bf07f7..f665ced3dbc 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -25,7 +25,6 @@ use hir as ast;
 use hir::map::{self, Node};
 use hir::{Expr, FnDecl};
 use hir::intravisit::FnKind;
-use rustc_target::spec::abi;
 use syntax::ast::{Attribute, Name, NodeId};
 use syntax_pos::Span;
 
@@ -105,9 +104,7 @@ impl<'a> Code<'a> {
 struct ItemFnParts<'a> {
     name:     Name,
     decl:     &'a ast::FnDecl,
-    unsafety: ast::Unsafety,
-    constness: ast::Constness,
-    abi:      abi::Abi,
+    header:   ast::FnHeader,
     vis:      &'a ast::Visibility,
     generics: &'a ast::Generics,
     body:     ast::BodyId,
@@ -183,31 +180,31 @@ impl<'a> FnLikeNode<'a> {
 
     pub fn constness(self) -> ast::Constness {
         match self.kind() {
-            FnKind::ItemFn(_, _, _, constness, ..) => {
-                constness
-            }
-            FnKind::Method(_, m, ..) => {
-                m.constness
-            }
+            FnKind::ItemFn(_, _, header, ..) => header.constness,
+            FnKind::Method(_, m, ..) => m.header.constness,
             _ => ast::Constness::NotConst
         }
     }
 
+    pub fn asyncness(self) -> ast::IsAsync {
+        match self.kind() {
+            FnKind::ItemFn(_, _, header, ..) => header.asyncness,
+            FnKind::Method(_, m, ..) => m.header.asyncness,
+            _ => ast::IsAsync::NotAsync
+        }
+    }
+
     pub fn unsafety(self) -> ast::Unsafety {
         match self.kind() {
-            FnKind::ItemFn(_, _, unsafety, ..) => {
-                unsafety
-            }
-            FnKind::Method(_, m, ..) => {
-                m.unsafety
-            }
+            FnKind::ItemFn(_, _, header, ..) => header.unsafety,
+            FnKind::Method(_, m, ..) => m.header.unsafety,
             _ => ast::Unsafety::Normal
         }
     }
 
     pub fn kind(self) -> FnKind<'a> {
         let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
-            FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis, p.attrs)
+            FnKind::ItemFn(p.name, p.generics, p.header, p.vis, p.attrs)
         };
         let closure = |c: ClosureParts<'a>| {
             FnKind::Closure(c.attrs)
@@ -232,19 +229,17 @@ impl<'a> FnLikeNode<'a> {
     {
         match self.node {
             map::NodeItem(i) => match i.node {
-                ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, block) =>
+                ast::ItemFn(ref decl, header, ref generics, block) =>
                     item_fn(ItemFnParts {
                         id: i.id,
                         name: i.name,
                         decl: &decl,
-                        unsafety,
                         body: block,
-                        generics,
-                        abi,
                         vis: &i.vis,
-                        constness,
                         span: i.span,
                         attrs: &i.attrs,
+                        header,
+                        generics,
                     }),
                 _ => bug!("item FnLikeNode that is not fn-like"),
             },
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index c2c8c7a391b..4ffe4f262ae 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -210,7 +210,7 @@ impl<'hir> MapEntry<'hir> {
                 match item.node {
                     ItemConst(_, body) |
                     ItemStatic(.., body) |
-                    ItemFn(_, _, _, _, _, body) => Some(body),
+                    ItemFn(_, _, _, body) => Some(body),
                     _ => None,
                 }
             }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index f6876113c11..9479234cf11 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1506,9 +1506,7 @@ pub struct MutTy {
 /// Represents a method's signature in a trait declaration or implementation.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct MethodSig {
-    pub unsafety: Unsafety,
-    pub constness: Constness,
-    pub abi: Abi,
+    pub header: FnHeader,
     pub decl: P<FnDecl>,
 }
 
@@ -1736,7 +1734,13 @@ pub enum IsAuto {
     No
 }
 
-#[derive(Copy, Clone, PartialEq, Eq,PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum IsAsync {
+    Async,
+    NotAsync,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Unsafety {
     Unsafe,
     Normal,
@@ -2012,6 +2016,25 @@ pub struct Item {
     pub span: Span,
 }
 
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct FnHeader {
+    pub unsafety: Unsafety,
+    pub constness: Constness,
+    pub asyncness: IsAsync,
+    pub abi: Abi,
+}
+
+impl Default for FnHeader {
+    fn default() -> FnHeader {
+        FnHeader {
+            unsafety: Unsafety::Normal,
+            constness: Constness::NotConst,
+            asyncness: IsAsync::NotAsync,
+            abi: Abi::Rust,
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Item_ {
     /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
@@ -2031,7 +2054,7 @@ pub enum Item_ {
     /// A `const` item
     ItemConst(P<Ty>, BodyId),
     /// A function declaration
-    ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, BodyId),
+    ItemFn(P<FnDecl>, FnHeader, Generics, BodyId),
     /// A module
     ItemMod(Mod),
     /// An external module
@@ -2096,7 +2119,7 @@ impl Item_ {
 
     pub fn generics(&self) -> Option<&Generics> {
         Some(match *self {
-            ItemFn(_, _, _, _, ref generics, _) |
+            ItemFn(_, _, ref generics, _) |
             ItemTy(_, ref generics) |
             ItemEnum(_, ref generics) |
             ItemStruct(_, ref generics) |
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 14f780fab7f..4db2247103e 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -459,9 +459,7 @@ impl<'a> State<'a> {
             hir::ForeignItemFn(ref decl, ref arg_names, ref generics) => {
                 self.head("")?;
                 self.print_fn(decl,
-                              hir::Unsafety::Normal,
-                              hir::Constness::NotConst,
-                              Abi::Rust,
+                              hir::FnHeader::default(),
                               Some(item.name),
                               generics,
                               &item.vis,
@@ -598,12 +596,10 @@ impl<'a> State<'a> {
                 self.s.word(";")?;
                 self.end()?; // end the outer cbox
             }
-            hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, body) => {
+            hir::ItemFn(ref decl, header, ref typarams, body) => {
                 self.head("")?;
                 self.print_fn(decl,
-                              unsafety,
-                              constness,
-                              abi,
+                              header,
                               Some(item.name),
                               typarams,
                               &item.vis,
@@ -935,9 +931,7 @@ impl<'a> State<'a> {
                             body_id: Option<hir::BodyId>)
                             -> io::Result<()> {
         self.print_fn(&m.decl,
-                      m.unsafety,
-                      m.constness,
-                      m.abi,
+                      m.header,
                       Some(name),
                       generics,
                       vis,
@@ -1986,16 +1980,14 @@ impl<'a> State<'a> {
 
     pub fn print_fn(&mut self,
                     decl: &hir::FnDecl,
-                    unsafety: hir::Unsafety,
-                    constness: hir::Constness,
-                    abi: Abi,
+                    header: hir::FnHeader,
                     name: Option<ast::Name>,
                     generics: &hir::Generics,
                     vis: &hir::Visibility,
                     arg_names: &[Spanned<ast::Name>],
                     body_id: Option<hir::BodyId>)
                     -> io::Result<()> {
-        self.print_fn_header_info(unsafety, constness, abi, vis)?;
+        self.print_fn_header_info(header, vis)?;
 
         if let Some(name) = name {
             self.nbsp()?;
@@ -2260,9 +2252,10 @@ impl<'a> State<'a> {
             span: syntax_pos::DUMMY_SP,
         };
         self.print_fn(decl,
-                      unsafety,
-                      hir::Constness::NotConst,
-                      abi,
+                      hir::FnHeader {
+                          unsafety, abi,
+                          ..hir::FnHeader::default()
+                      },
                       name,
                       &generics,
                       &hir::Inherited,
@@ -2333,22 +2326,26 @@ impl<'a> State<'a> {
     }
 
     pub fn print_fn_header_info(&mut self,
-                                unsafety: hir::Unsafety,
-                                constness: hir::Constness,
-                                abi: Abi,
+                                header: hir::FnHeader,
                                 vis: &hir::Visibility)
                                 -> io::Result<()> {
         self.s.word(&visibility_qualified(vis, ""))?;
-        self.print_unsafety(unsafety)?;
 
-        match constness {
+        match header.constness {
             hir::Constness::NotConst => {}
             hir::Constness::Const => self.word_nbsp("const")?,
         }
 
-        if abi != Abi::Rust {
+        match header.asyncness {
+            hir::IsAsync::NotAsync => {}
+            hir::IsAsync::Async => self.word_nbsp("async")?,
+        }
+
+        self.print_unsafety(header.unsafety)?;
+
+        if header.abi != Abi::Rust {
             self.word_nbsp("extern")?;
-            self.word_nbsp(&abi.to_string())?;
+            self.word_nbsp(&header.abi.to_string())?;
         }
 
         self.s.word("fn")
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 882194ae64e..b1429247ab0 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -272,9 +272,7 @@ impl_stable_hash_for!(struct hir::MutTy {
 });
 
 impl_stable_hash_for!(struct hir::MethodSig {
-    unsafety,
-    constness,
-    abi,
+    header,
     decl
 });
 
@@ -285,6 +283,13 @@ impl_stable_hash_for!(struct hir::TypeBinding {
     span
 });
 
+impl_stable_hash_for!(struct hir::FnHeader {
+    unsafety,
+    constness,
+    asyncness,
+    abi
+});
+
 impl<'a> HashStable<StableHashingContext<'a>> for hir::Ty {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
@@ -897,7 +902,7 @@ impl_stable_hash_for!(enum hir::Item_ {
     ItemUse(path, use_kind),
     ItemStatic(ty, mutability, body_id),
     ItemConst(ty, body_id),
-    ItemFn(fn_decl, unsafety, constness, abi, generics, body_id),
+    ItemFn(fn_decl, header, generics, body_id),
     ItemMod(module),
     ItemForeignMod(foreign_mod),
     ItemGlobalAsm(global_asm),
@@ -1100,6 +1105,10 @@ impl_stable_hash_for!(enum hir::Unsafety {
     Normal
 });
 
+impl_stable_hash_for!(enum hir::IsAsync {
+    Async,
+    NotAsync
+});
 
 impl_stable_hash_for!(enum hir::Constness {
     Const,
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 7f81af7e46c..95829346ede 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -238,8 +238,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             // If we are building an executable, only explicitly extern
             // types need to be exported.
             if let hir_map::NodeItem(item) = *node {
-                let reachable = if let hir::ItemFn(.., abi, _, _) = item.node {
-                    abi != Abi::Rust
+                let reachable = if let hir::ItemFn(_, header, ..) = item.node {
+                    header.abi != Abi::Rust
                 } else {
                     false
                 };
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index f73e0ab2a9d..c2623f40356 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -476,7 +476,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         match item.node {
-            hir::ItemFn(ref decl, _, _, _, ref generics, _) => {
+            hir::ItemFn(ref decl, _, ref generics, _) => {
                 self.visit_early_late(None, decl, generics, |this| {
                     intravisit::walk_item(this, item);
                 });
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index ec0676259ef..78406e88c75 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -10,12 +10,11 @@
 
 use rustc::middle::allocator::AllocatorKind;
 use rustc_errors;
-use rustc_target::spec::abi::Abi;
 use syntax::ast::{Attribute, Crate, LitKind, StrStyle};
-use syntax::ast::{Arg, Constness, Generics, Mac, Mutability, Ty, Unsafety};
+use syntax::ast::{Arg, FnHeader, Generics, Mac, Mutability, Ty, Unsafety};
 use syntax::ast::{self, Expr, Ident, Item, ItemKind, TyKind, VisibilityKind};
 use syntax::attr;
-use syntax::codemap::{dummy_spanned, respan};
+use syntax::codemap::respan;
 use syntax::codemap::{ExpnInfo, MacroAttribute, NameAndSpan};
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::base::Resolver;
@@ -152,9 +151,10 @@ impl<'a> AllocFnFactory<'a> {
         let (output_ty, output_expr) = self.ret_ty(&method.output, result);
         let kind = ItemKind::Fn(
             self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
-            Unsafety::Unsafe,
-            dummy_spanned(Constness::NotConst),
-            Abi::Rust,
+            FnHeader {
+                unsafety: Unsafety::Unsafe,
+                ..FnHeader::default()
+            },
             Generics::default(),
             self.cx.block_expr(output_expr),
         );
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 67720e61e91..38ecbf5ca8a 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -712,8 +712,8 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
     fn fold_item_kind(&mut self, i: ast::ItemKind) -> ast::ItemKind {
         let is_const = match i {
             ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
-            ast::ItemKind::Fn(ref decl, _, ref constness, _, _, _) =>
-                constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
+            ast::ItemKind::Fn(ref decl, ref header, _, _) =>
+                header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
             _ => false,
         };
         self.run(is_const, |s| fold::noop_fold_item_kind(i, s))
@@ -722,8 +722,8 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
     fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
         let is_const = match i.node {
             ast::TraitItemKind::Const(..) => true,
-            ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) =>
-                constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
+            ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
+                header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
             _ => false,
         };
         self.run(is_const, |s| fold::noop_fold_trait_item(i, s))
@@ -732,8 +732,8 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
     fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> {
         let is_const = match i.node {
             ast::ImplItemKind::Const(..) => true,
-            ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) =>
-                constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
+            ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
+                header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
             _ => false,
         };
         self.run(is_const, |s| fold::noop_fold_impl_item(i, s))
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
index 8f8fe04fd8e..1b5361187f3 100644
--- a/src/librustc_lint/bad_style.rs
+++ b/src/librustc_lint/bad_style.rs
@@ -284,9 +284,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
                     _ => (),
                 }
             }
-            FnKind::ItemFn(name, _, _, _, abi, _, attrs) => {
+            FnKind::ItemFn(name, _, header, _, attrs) => {
                 // Skip foreign-ABI #[no_mangle] functions (Issue #31924)
-                if abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() {
+                if header.abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() {
                     return;
                 }
                 self.check_snake_case(cx, "function", &name.as_str(), Some(span))
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 941fabe26a6..d6120ab2079 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -259,12 +259,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
                 span: Span,
                 _: ast::NodeId) {
         match fk {
-            FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, ..) => {
+            FnKind::ItemFn(_, _, hir::FnHeader { unsafety: hir::Unsafety::Unsafe, .. }, ..) => {
                 self.report_unsafe(cx, span, "declaration of an `unsafe` function")
             }
 
             FnKind::Method(_, sig, ..) => {
-                if sig.unsafety == hir::Unsafety::Unsafe {
+                if sig.header.unsafety == hir::Unsafety::Unsafe {
                     self.report_unsafe(cx, span, "implementation of an `unsafe` method")
                 }
             }
@@ -275,7 +275,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
 
     fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
         if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) = item.node {
-            if sig.unsafety == hir::Unsafety::Unsafe {
+            if sig.header.unsafety == hir::Unsafety::Unsafe {
                 self.report_unsafe(cx, item.span, "declaration of an `unsafe` method")
             }
         }
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index cbe9615c693..7ed3abe66c2 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -917,7 +917,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
             ty::AssociatedKind::Method => {
                 let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
                     FnData {
-                        constness: sig.constness,
+                        constness: sig.header.constness,
                         arg_names: self.encode_fn_arg_names_for_body(body),
                         sig: self.lazy(&tcx.fn_sig(def_id)),
                     }
@@ -941,7 +941,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     let needs_inline = (generics.requires_monomorphization(self.tcx) ||
                                         tcx.codegen_fn_attrs(def_id).requests_inline()) &&
                                         !self.metadata_output_only();
-                    let is_const_fn = sig.constness == hir::Constness::Const;
+                    let is_const_fn = sig.header.constness == hir::Constness::Const;
                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                     needs_inline || is_const_fn || always_encode_mir
                 },
@@ -1045,9 +1045,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     self.encode_rendered_const_for_body(body_id)
                 )
             }
-            hir::ItemFn(_, _, constness, .., body) => {
+            hir::ItemFn(_, header, .., body) => {
                 let data = FnData {
-                    constness,
+                    constness: header.constness,
                     arg_names: self.encode_fn_arg_names_for_body(body),
                     sig: self.lazy(&tcx.fn_sig(def_id)),
                 };
@@ -1235,7 +1235,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     self.encode_optimized_mir(def_id)
                 }
                 hir::ItemConst(..) => self.encode_optimized_mir(def_id),
-                hir::ItemFn(_, _, constness, ..) => {
+                hir::ItemFn(_, header, ..) => {
                     let generics = tcx.generics_of(def_id);
                     let has_types = generics.params.iter().any(|param| match param.kind {
                         ty::GenericParamDefKind::Type { .. } => true,
@@ -1245,7 +1245,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                         (has_types || tcx.codegen_fn_attrs(def_id).requests_inline()) &&
                             !self.metadata_output_only();
                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
-                    if needs_inline || constness == hir::Constness::Const || always_encode_mir {
+                    if needs_inline || header.constness == hir::Constness::Const || always_encode_mir {
                         self.encode_optimized_mir(def_id)
                     } else {
                         None
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 5f8f9acae83..00e064fbb47 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -380,10 +380,10 @@ fn is_enclosed(tcx: TyCtxt,
         if used_unsafe.contains(&parent_id) {
             Some(("block".to_string(), parent_id))
         } else if let Some(hir::map::NodeItem(&hir::Item {
-            node: hir::ItemFn(_, fn_unsafety, _, _, _, _),
+            node: hir::ItemFn(_, header, _, _),
             ..
         })) = tcx.hir.find(parent_id) {
-            match fn_unsafety {
+            match header.unsafety {
                 hir::Unsafety::Unsafe => Some(("fn".to_string(), parent_id)),
                 hir::Unsafety::Normal => None,
             }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index fc54d323b0f..8111caed5c5 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -257,7 +257,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 for impl_item in impl_items {
                     self.invalid_visibility(&impl_item.vis, None);
                     if let ImplItemKind::Method(ref sig, _) = impl_item.node {
-                        self.check_trait_fn_not_const(sig.constness);
+                        self.check_trait_fn_not_const(sig.header.constness);
                     }
                 }
             }
@@ -309,7 +309,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self.no_questions_in_bounds(bounds, "supertraits", true);
                 for trait_item in trait_items {
                     if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
-                        self.check_trait_fn_not_const(sig.constness);
+                        self.check_trait_fn_not_const(sig.header.constness);
                         if block.is_none() {
                             self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
                                 if mut_ident {
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 7f2f0b0c837..b532aaf90df 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -380,17 +380,20 @@ impl Sig for ast::Item {
 
                 Ok(extend_sig(ty, text, defs, vec![]))
             }
-            ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, _) => {
+            ast::ItemKind::Fn(ref decl, header, ref generics, _) => {
                 let mut text = String::new();
-                if constness.node == ast::Constness::Const {
+                if header.constness.node == ast::Constness::Const {
                     text.push_str("const ");
                 }
-                if unsafety == ast::Unsafety::Unsafe {
+                if header.asyncness == ast::IsAsync::Async {
+                    text.push_str("async ");
+                }
+                if header.unsafety == ast::Unsafety::Unsafe {
                     text.push_str("unsafe ");
                 }
-                if abi != ::rustc_target::spec::abi::Abi::Rust {
+                if header.abi != ::rustc_target::spec::abi::Abi::Rust {
                     text.push_str("extern");
-                    text.push_str(&abi.to_string());
+                    text.push_str(&header.abi.to_string());
                     text.push(' ');
                 }
                 text.push_str("fn ");
@@ -914,15 +917,18 @@ fn make_method_signature(
 ) -> Result {
     // FIXME code dup with function signature
     let mut text = String::new();
-    if m.constness.node == ast::Constness::Const {
+    if m.header.constness.node == ast::Constness::Const {
         text.push_str("const ");
     }
-    if m.unsafety == ast::Unsafety::Unsafe {
+    if m.header.asyncness == ast::IsAsync::Async {
+        text.push_str("async ");
+    }
+    if m.header.unsafety == ast::Unsafety::Unsafe {
         text.push_str("unsafe ");
     }
-    if m.abi != ::rustc_target::spec::abi::Abi::Rust {
+    if m.header.abi != ::rustc_target::spec::abi::Abi::Rust {
         text.push_str("extern");
-        text.push_str(&m.abi.to_string());
+        text.push_str(&m.header.abi.to_string());
         text.push(' ');
     }
     text.push_str("fn ");
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 4c849cad187..824346dab94 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1181,13 +1181,13 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let icx = ItemCtxt::new(tcx, def_id);
 
     match tcx.hir.get(node_id) {
-        NodeTraitItem(&hir::TraitItem { node: TraitItemKind::Method(ref sig, _), .. }) |
-        NodeImplItem(&hir::ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) => {
-            AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl)
+        NodeTraitItem(hir::TraitItem { node: TraitItemKind::Method(sig, _), .. }) |
+        NodeImplItem(hir::ImplItem { node: ImplItemKind::Method(sig, _), .. }) => {
+            AstConv::ty_of_fn(&icx, sig.header.unsafety, sig.header.abi, &sig.decl)
         }
 
-        NodeItem(&hir::Item { node: ItemFn(ref decl, unsafety, _, abi, _, _), .. }) => {
-            AstConv::ty_of_fn(&icx, unsafety, abi, decl)
+        NodeItem(hir::Item { node: ItemFn(decl, header, _, _), .. }) => {
+            AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl)
         }
 
         NodeForeignItem(&hir::ForeignItem { node: ForeignItemFn(ref fn_decl, _, _), .. }) => {
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 114cb0e455d..0021ceac315 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -198,9 +198,12 @@ fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function {
     clean::Function {
         decl: (did, sig).clean(cx),
         generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
-        unsafety: sig.unsafety(),
-        constness,
-        abi: sig.abi(),
+        header: hir::FnHeader {
+            unsafety: sig.unsafety(),
+            abi: sig.abi(),
+            constness,
+            ..hir::FnHeader::default()
+        }
     }
 }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0979c3d8558..7bebefc41f9 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -18,8 +18,8 @@ pub use self::SelfTy::*;
 pub use self::FunctionRetTy::*;
 pub use self::Visibility::{Public, Inherited};
 
-use syntax;
 use rustc_target::spec::abi::Abi;
+use syntax;
 use syntax::ast::{self, AttrStyle, NodeId, Ident};
 use syntax::attr;
 use syntax::codemap::{dummy_spanned, Spanned};
@@ -2074,10 +2074,8 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Method {
     pub generics: Generics,
-    pub unsafety: hir::Unsafety,
-    pub constness: hir::Constness,
     pub decl: FnDecl,
-    pub abi: Abi,
+    pub header: hir::FnHeader,
 }
 
 impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) {
@@ -2088,28 +2086,23 @@ impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId)
         Method {
             decl,
             generics,
-            unsafety: self.0.unsafety,
-            constness: self.0.constness,
-            abi: self.0.abi
+            header: self.0.header,
         }
     }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct TyMethod {
-    pub unsafety: hir::Unsafety,
+    pub header: hir::FnHeader,
     pub decl: FnDecl,
     pub generics: Generics,
-    pub abi: Abi,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Function {
     pub decl: FnDecl,
     pub generics: Generics,
-    pub unsafety: hir::Unsafety,
-    pub constness: hir::Constness,
-    pub abi: Abi,
+    pub header: hir::FnHeader,
 }
 
 impl Clean<Item> for doctree::Function {
@@ -2128,9 +2121,7 @@ impl Clean<Item> for doctree::Function {
             inner: FunctionItem(Function {
                 decl,
                 generics,
-                unsafety: self.unsafety,
-                constness: self.constness,
-                abi: self.abi,
+                header: self.header,
             }),
         }
     }
@@ -2359,10 +2350,9 @@ impl Clean<Item> for hir::TraitItem {
                     (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
                 });
                 TyMethodItem(TyMethod {
-                    unsafety: sig.unsafety.clone(),
+                    header: sig.header,
                     decl,
                     generics,
-                    abi: sig.abi
                 })
             }
             hir::TraitItemKind::Type(ref bounds, ref default) => {
@@ -2461,18 +2451,24 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
                         hir::Constness::NotConst
                     };
                     MethodItem(Method {
-                        unsafety: sig.unsafety(),
                         generics,
                         decl,
-                        abi: sig.abi(),
-                        constness,
+                        header: hir::FnHeader {
+                            unsafety: sig.unsafety(),
+                            abi: sig.abi(),
+                            constness,
+                            ..hir::FnHeader::default()
+                        }
                     })
                 } else {
                     TyMethodItem(TyMethod {
-                        unsafety: sig.unsafety(),
                         generics,
                         decl,
-                        abi: sig.abi(),
+                        header: hir::FnHeader {
+                            unsafety: sig.unsafety(),
+                            abi: sig.abi(),
+                            ..hir::FnHeader::default()
+                        }
                     })
                 }
             }
@@ -3697,9 +3693,9 @@ impl Clean<BareFunctionDecl> for hir::BareFnTy {
         });
         BareFunctionDecl {
             unsafety: self.unsafety,
+            abi: self.abi,
             decl,
             generic_params,
-            abi: self.abi,
         }
     }
 }
@@ -3994,7 +3990,7 @@ impl Clean<Vec<Item>> for hir::ForeignMod {
         let mut items = self.items.clean(cx);
         for item in &mut items {
             if let ForeignFunctionItem(ref mut f) = item.inner {
-                f.abi = self.abi;
+                f.header.abi = self.abi;
             }
         }
         items
@@ -4011,9 +4007,7 @@ impl Clean<Item> for hir::ForeignItem {
                 ForeignFunctionItem(Function {
                     decl,
                     generics,
-                    unsafety: hir::Unsafety::Unsafe,
-                    abi: Abi::Rust,
-                    constness: hir::Constness::NotConst,
+                    header: hir::FnHeader::default(),
                 })
             }
             hir::ForeignItemStatic(ref ty, mutbl) => {
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 16d14bc56d6..0807db29976 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -13,7 +13,6 @@
 pub use self::StructType::*;
 pub use self::TypeBound::*;
 
-use rustc_target::spec::abi;
 use syntax::ast;
 use syntax::ast::{Name, NodeId};
 use syntax::attr;
@@ -149,11 +148,9 @@ pub struct Function {
     pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
-    pub unsafety: hir::Unsafety,
-    pub constness: hir::Constness,
+    pub header: hir::FnHeader,
     pub whence: Span,
     pub generics: hir::Generics,
-    pub abi: abi::Abi,
     pub body: hir::BodyId,
 }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 180591b3532..cfcaf23c4ff 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -62,7 +62,6 @@ use rustc::middle::stability;
 use rustc::hir;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::flock;
-use rustc_target::spec::abi;
 
 use clean::{self, AttributesExt, GetDefId, SelfTy, Mutability};
 use doctree;
@@ -2405,7 +2404,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
 
                 let unsafety_flag = match myitem.inner {
                     clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func)
-                    if func.unsafety == hir::Unsafety::Unsafe => {
+                    if func.header.unsafety == hir::Unsafety::Unsafe => {
                         "<a title='unsafe function' href='#'><sup>⚠</sup></a>"
                     }
                     _ => "",
@@ -2577,9 +2576,9 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                  f: &clean::Function) -> fmt::Result {
     let name_len = format!("{}{}{}{:#}fn {}{:#}",
                            VisSpace(&it.visibility),
-                           ConstnessSpace(f.constness),
-                           UnsafetySpace(f.unsafety),
-                           AbiSpace(f.abi),
+                           ConstnessSpace(f.header.constness),
+                           UnsafetySpace(f.header.unsafety),
+                           AbiSpace(f.header.abi),
                            it.name.as_ref().unwrap(),
                            f.generics).len();
     write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it)?)?;
@@ -2587,9 +2586,9 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     write!(w,
            "{vis}{constness}{unsafety}{abi}fn {name}{generics}{decl}{where_clause}</pre>",
            vis = VisSpace(&it.visibility),
-           constness = ConstnessSpace(f.constness),
-           unsafety = UnsafetySpace(f.unsafety),
-           abi = AbiSpace(f.abi),
+           constness = ConstnessSpace(f.header.constness),
+           unsafety = UnsafetySpace(f.header.unsafety),
+           abi = AbiSpace(f.header.abi),
            name = it.name.as_ref().unwrap(),
            generics = f.generics,
            where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
@@ -2999,9 +2998,7 @@ fn render_assoc_item(w: &mut fmt::Formatter,
                      parent: ItemType) -> fmt::Result {
     fn method(w: &mut fmt::Formatter,
               meth: &clean::Item,
-              unsafety: hir::Unsafety,
-              constness: hir::Constness,
-              abi: abi::Abi,
+              header: hir::FnHeader,
               g: &clean::Generics,
               d: &clean::FnDecl,
               link: AssocItemLink,
@@ -3026,9 +3023,9 @@ fn render_assoc_item(w: &mut fmt::Formatter,
         };
         let mut head_len = format!("{}{}{}{:#}fn {}{:#}",
                                    VisSpace(&meth.visibility),
-                                   ConstnessSpace(constness),
-                                   UnsafetySpace(unsafety),
-                                   AbiSpace(abi),
+                                   ConstnessSpace(header.constness),
+                                   UnsafetySpace(header.unsafety),
+                                   AbiSpace(header.abi),
                                    name,
                                    *g).len();
         let (indent, end_newline) = if parent == ItemType::Trait {
@@ -3041,9 +3038,9 @@ fn render_assoc_item(w: &mut fmt::Formatter,
         write!(w, "{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
                VisSpace(&meth.visibility),
-               ConstnessSpace(constness),
-               UnsafetySpace(unsafety),
-               AbiSpace(abi),
+               ConstnessSpace(header.constness),
+               UnsafetySpace(header.unsafety),
+               AbiSpace(header.abi),
                href = href,
                name = name,
                generics = *g,
@@ -3061,12 +3058,10 @@ fn render_assoc_item(w: &mut fmt::Formatter,
     match item.inner {
         clean::StrippedItem(..) => Ok(()),
         clean::TyMethodItem(ref m) => {
-            method(w, item, m.unsafety, hir::Constness::NotConst,
-                   m.abi, &m.generics, &m.decl, link, parent)
+            method(w, item, m.header, &m.generics, &m.decl, link, parent)
         }
         clean::MethodItem(ref m) => {
-            method(w, item, m.unsafety, m.constness,
-                   m.abi, &m.generics, &m.decl, link, parent)
+            method(w, item, m.header, &m.generics, &m.decl, link, parent)
         }
         clean::AssociatedConstItem(ref ty, ref default) => {
             assoc_const(w, item, ty, default.as_ref(), link)
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 10b1a2e1e0b..6bf1931e468 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -13,7 +13,6 @@
 
 use std::mem;
 
-use rustc_target::spec::abi;
 use syntax::ast;
 use syntax::attr;
 use syntax_pos::Span;
@@ -172,9 +171,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
 
     pub fn visit_fn(&mut self, item: &hir::Item,
                     name: ast::Name, fd: &hir::FnDecl,
-                    unsafety: &hir::Unsafety,
-                    constness: hir::Constness,
-                    abi: &abi::Abi,
+                    header: hir::FnHeader,
                     gen: &hir::Generics,
                     body: hir::BodyId) -> Function {
         debug!("Visiting fn");
@@ -188,9 +185,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
             name,
             whence: item.span,
             generics: gen.clone(),
-            unsafety: *unsafety,
-            constness,
-            abi: *abi,
+            header,
             body,
         }
     }
@@ -463,9 +458,8 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
                 om.structs.push(self.visit_variant_data(item, name, sd, gen)),
             hir::ItemUnion(ref sd, ref gen) =>
                 om.unions.push(self.visit_union_data(item, name, sd, gen)),
-            hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, body) =>
-                om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
-                                          constness, abi, gen, body)),
+            hir::ItemFn(ref fd, header, ref gen, body) =>
+                om.fns.push(self.visit_fn(item, name, &**fd, header, gen, body)),
             hir::ItemTy(ref ty, ref gen) => {
                 let t = Typedef {
                     ty: ty.clone(),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index c6de2c4da39..55c21c64c83 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -17,7 +17,7 @@ pub use util::ThinVec;
 pub use util::parser::ExprPrecedence;
 
 use syntax_pos::{Span, DUMMY_SP};
-use codemap::{respan, Spanned};
+use codemap::{dummy_spanned, respan, Spanned};
 use rustc_target::spec::abi::Abi;
 use ext::hygiene::{Mark, SyntaxContext};
 use print::pprust;
@@ -1325,9 +1325,7 @@ pub struct MutTy {
 /// or in an implementation.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct MethodSig {
-    pub unsafety: Unsafety,
-    pub constness: Spanned<Constness>,
-    pub abi: Abi,
+    pub header: FnHeader,
     pub decl: P<FnDecl>,
 }
 
@@ -1709,6 +1707,12 @@ pub enum Unsafety {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum IsAsync {
+    Async,
+    NotAsync,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Constness {
     Const,
     NotConst,
@@ -2009,6 +2013,29 @@ pub struct Item {
     pub tokens: Option<TokenStream>,
 }
 
+/// A function header
+///
+/// All the information between the visibility & the name of the function is
+/// included in this struct (e.g. `async unsafe fn` or `const extern "C" fn`)
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct FnHeader {
+    pub unsafety: Unsafety,
+    pub asyncness: IsAsync,
+    pub constness: Spanned<Constness>,
+    pub abi: Abi,
+}
+
+impl Default for FnHeader {
+    fn default() -> FnHeader {
+        FnHeader {
+            unsafety: Unsafety::Normal,
+            asyncness: IsAsync::NotAsync,
+            constness: dummy_spanned(Constness::NotConst),
+            abi: Abi::Rust,
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum ItemKind {
     /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
@@ -2030,7 +2057,7 @@ pub enum ItemKind {
     /// A function declaration (`fn` or `pub fn`).
     ///
     /// E.g. `fn foo(bar: usize) -> usize { .. }`
-    Fn(P<FnDecl>, Unsafety, Spanned<Constness>, Abi, Generics, P<Block>),
+    Fn(P<FnDecl>, FnHeader, Generics, P<Block>),
     /// A module declaration (`mod` or `pub mod`).
     ///
     /// E.g. `mod foo;` or `mod foo { .. }`
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 9044cab05d6..6bb7535544b 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -1008,9 +1008,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                   name,
                   Vec::new(),
                   ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)),
-                              ast::Unsafety::Normal,
-                              dummy_spanned(ast::Constness::NotConst),
-                              Abi::Rust,
+                              ast::FnHeader {
+                                  unsafety: ast::Unsafety::Normal,
+                                  asyncness: ast::IsAsync::NotAsync,
+                                  constness: dummy_spanned(ast::Constness::NotConst),
+                                  abi: Abi::Rust,
+                              },
                               generics,
                               body))
     }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index be4cf197be4..a9679f86ddb 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -29,7 +29,6 @@ use rustc_target::spec::abi::Abi;
 use ast::{self, NodeId, PatKind, RangeEnd};
 use attr;
 use edition::{ALL_EDITIONS, Edition};
-use codemap::Spanned;
 use syntax_pos::{Span, DUMMY_SP};
 use errors::{DiagnosticBuilder, Handler, FatalError};
 use visit::{self, FnKind, Visitor};
@@ -468,12 +467,14 @@ declare_features! (
     // 'a: { break 'a; }
     (active, label_break_value, "1.28.0", Some(48594), None),
 
-
     // #[panic_implementation]
     (active, panic_implementation, "1.28.0", Some(44489), None),
 
     // #[doc(keyword = "...")]
     (active, doc_keyword, "1.28.0", Some(51315), None),
+
+    // Allows async and await syntax
+    (active, async_await, "1.28.0", Some(0), Some(Edition::Edition2018)),
 );
 
 declare_features! (
@@ -1760,20 +1761,24 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 fn_decl: &'a ast::FnDecl,
                 span: Span,
                 _node_id: NodeId) {
-        // check for const fn declarations
-        if let FnKind::ItemFn(_, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
-            fn_kind {
-            gate_feature_post!(&self, const_fn, span, "const fn is unstable");
-        }
-        // stability of const fn methods are covered in
-        // visit_trait_item and visit_impl_item below; this is
-        // because default methods don't pass through this
-        // point.
-
         match fn_kind {
-            FnKind::ItemFn(_, _, _, abi, _, _) |
-            FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
-                self.check_abi(abi, span);
+            FnKind::ItemFn(_, header, _, _) => {
+                // check for const fn and async fn declarations
+                if header.asyncness == ast::IsAsync::Async {
+                    gate_feature_post!(&self, async_await, span, "async fn is unstable");
+                }
+                if header.constness.node == ast::Constness::Const {
+                    gate_feature_post!(&self, const_fn, span, "const fn is unstable");
+                }
+                // stability of const fn methods are covered in
+                // visit_trait_item and visit_impl_item below; this is
+                // because default methods don't pass through this
+                // point.
+
+                self.check_abi(header.abi, span);
+            }
+            FnKind::Method(_, sig, _, _) => {
+                self.check_abi(sig.header.abi, span);
             }
             _ => {}
         }
@@ -1784,9 +1789,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         match ti.node {
             ast::TraitItemKind::Method(ref sig, ref block) => {
                 if block.is_none() {
-                    self.check_abi(sig.abi, ti.span);
+                    self.check_abi(sig.header.abi, ti.span);
                 }
-                if sig.constness.node == ast::Constness::Const {
+                if sig.header.constness.node == ast::Constness::Const {
                     gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
                 }
             }
@@ -1820,7 +1825,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
         match ii.node {
             ast::ImplItemKind::Method(ref sig, _) => {
-                if sig.constness.node == ast::Constness::Const {
+                if sig.header.constness.node == ast::Constness::Const {
                     gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
                 }
             }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 93248fe3bfa..941d2180fd1 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -881,11 +881,11 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
         ItemKind::Const(t, e) => {
             ItemKind::Const(folder.fold_ty(t), folder.fold_expr(e))
         }
-        ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
+        ItemKind::Fn(decl, header, generics, body) => {
             let generics = folder.fold_generics(generics);
             let decl = folder.fold_fn_decl(decl);
             let body = folder.fold_block(body);
-            ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
+            ItemKind::Fn(decl, header, generics, body)
         }
         ItemKind::Mod(m) => ItemKind::Mod(folder.fold_mod(m)),
         ItemKind::ForeignMod(nm) => ItemKind::ForeignMod(folder.fold_foreign_mod(nm)),
@@ -1082,9 +1082,7 @@ pub fn noop_fold_foreign_item_simple<T: Folder>(ni: ForeignItem, folder: &mut T)
 
 pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> MethodSig {
     MethodSig {
-        abi: sig.abi,
-        unsafety: sig.unsafety,
-        constness: sig.constness,
+        header: sig.header,
         decl: folder.fold_fn_decl(sig.decl)
     }
 }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 0050434d42e..61f88f3a250 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -928,12 +928,15 @@ mod tests {
                                     output: ast::FunctionRetTy::Default(sp(15, 15)),
                                     variadic: false
                                 }),
-                                        ast::Unsafety::Normal,
-                                        Spanned {
-                                            span: sp(0,2),
-                                            node: ast::Constness::NotConst,
+                                        ast::FnHeader {
+                                            unsafety: ast::Unsafety::Normal,
+                                            asyncness: ast::IsAsync::NotAsync,
+                                            constness: Spanned {
+                                                span: sp(0,2),
+                                                node: ast::Constness::NotConst,
+                                            },
+                                            abi: Abi::Rust,
                                         },
-                                        Abi::Rust,
                                         ast::Generics{
                                             params: Vec::new(),
                                             where_clause: ast::WhereClause {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 3955ccb4c42..d897aaadf43 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -19,11 +19,11 @@ use ast::{Constness, Crate};
 use ast::Defaultness;
 use ast::EnumDef;
 use ast::{Expr, ExprKind, RangeLimits};
-use ast::{Field, FnDecl};
+use ast::{Field, FnDecl, FnHeader};
 use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
 use ast::{GenericParam, GenericParamKind};
 use ast::GenericArg;
-use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
+use ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind};
 use ast::{Label, Lifetime, Lit, LitKind};
 use ast::Local;
 use ast::MacStmtStyle;
@@ -1356,10 +1356,13 @@ impl<'a> Parser<'a> {
             generics.where_clause = self.parse_where_clause()?;
 
             let sig = ast::MethodSig {
-                unsafety,
-                constness,
+                header: FnHeader {
+                    unsafety,
+                    constness,
+                    abi,
+                    asyncness: IsAsync::NotAsync,
+                },
                 decl: d,
-                abi,
             };
 
             let body = match self.token {
@@ -5349,6 +5352,7 @@ impl<'a> Parser<'a> {
     /// Parse an item-position function declaration.
     fn parse_item_fn(&mut self,
                      unsafety: Unsafety,
+                     asyncness: IsAsync,
                      constness: Spanned<Constness>,
                      abi: Abi)
                      -> PResult<'a, ItemInfo> {
@@ -5356,7 +5360,8 @@ impl<'a> Parser<'a> {
         let decl = self.parse_fn_decl(false)?;
         generics.where_clause = self.parse_where_clause()?;
         let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-        Ok((ident, ItemKind::Fn(decl, unsafety, constness, abi, generics, body), Some(inner_attrs)))
+        let header = FnHeader { unsafety, asyncness, constness, abi };
+        Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs)))
     }
 
     /// true if we are looking at `const ID`, false for things like `const fn` etc
@@ -5531,12 +5536,11 @@ impl<'a> Parser<'a> {
             generics.where_clause = self.parse_where_clause()?;
             *at_end = true;
             let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-            Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(ast::MethodSig {
-                abi,
-                unsafety,
-                constness,
-                decl,
-             }, body)))
+            let header = ast::FnHeader { abi, unsafety, constness, asyncness: IsAsync::NotAsync };
+            Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(
+                ast::MethodSig { header, decl },
+                body
+            )))
         }
     }
 
@@ -6622,6 +6626,7 @@ impl<'a> Parser<'a> {
                 let abi = opt_abi.unwrap_or(Abi::C);
                 let (ident, item_, extra_attrs) =
                     self.parse_item_fn(Unsafety::Normal,
+                                       IsAsync::NotAsync,
                                        respan(fn_span, Constness::NotConst),
                                        abi)?;
                 let prev_span = self.prev_span;
@@ -6665,6 +6670,7 @@ impl<'a> Parser<'a> {
                 self.bump();
                 let (ident, item_, extra_attrs) =
                     self.parse_item_fn(unsafety,
+                                       IsAsync::NotAsync,
                                        respan(const_span, Constness::Const),
                                        Abi::Rust)?;
                 let prev_span = self.prev_span;
@@ -6692,6 +6698,24 @@ impl<'a> Parser<'a> {
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
+        if self.eat_keyword(keywords::Async) {
+            // ASYNC FUNCTION ITEM
+            let unsafety = self.parse_unsafety();
+            self.expect_keyword(keywords::Fn)?;
+            let fn_span = self.prev_span;
+            let (ident, item_, extra_attrs) =
+                self.parse_item_fn(unsafety,
+                                   IsAsync::Async,
+                                   respan(fn_span, Constness::NotConst),
+                                   Abi::Rust)?;
+            let prev_span = self.prev_span;
+            let item = self.mk_item(lo.to(prev_span),
+                                    ident,
+                                    item_,
+                                    visibility,
+                                    maybe_append(attrs, extra_attrs));
+            return Ok(Some(item));
+        }
         if self.check_keyword(keywords::Unsafe) &&
             (self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) ||
             self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
@@ -6737,6 +6761,7 @@ impl<'a> Parser<'a> {
             let fn_span = self.prev_span;
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(Unsafety::Normal,
+                                   IsAsync::NotAsync,
                                    respan(fn_span, Constness::NotConst),
                                    Abi::Rust)?;
             let prev_span = self.prev_span;
@@ -6762,6 +6787,7 @@ impl<'a> Parser<'a> {
             let fn_span = self.prev_span;
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(Unsafety::Unsafe,
+                                   IsAsync::NotAsync,
                                    respan(fn_span, Constness::NotConst),
                                    abi)?;
             let prev_span = self.prev_span;
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 7a55919f422..210742c55a5 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -373,14 +373,13 @@ pub fn vis_to_string(v: &ast::Visibility) -> String {
 }
 
 pub fn fun_to_string(decl: &ast::FnDecl,
-                     unsafety: ast::Unsafety,
-                     constness: ast::Constness,
+                     header: ast::FnHeader,
                      name: ast::Ident,
                      generics: &ast::Generics)
                      -> String {
     to_string(|s| {
         s.head("")?;
-        s.print_fn(decl, unsafety, constness, Abi::Rust, Some(name),
+        s.print_fn(decl, header, Some(name),
                    generics, &codemap::dummy_spanned(ast::VisibilityKind::Inherited))?;
         s.end()?; // Close the head box
         s.end() // Close the outer box
@@ -1118,9 +1117,8 @@ impl<'a> State<'a> {
         match item.node {
             ast::ForeignItemKind::Fn(ref decl, ref generics) => {
                 self.head("")?;
-                self.print_fn(decl, ast::Unsafety::Normal,
-                              ast::Constness::NotConst,
-                              Abi::Rust, Some(item.ident),
+                self.print_fn(decl, ast::FnHeader::default(),
+                              Some(item.ident),
                               generics, &item.vis)?;
                 self.end()?; // end head-ibox
                 self.s.word(";")?;
@@ -1249,13 +1247,11 @@ impl<'a> State<'a> {
                 self.s.word(";")?;
                 self.end()?; // end the outer cbox
             }
-            ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
+            ast::ItemKind::Fn(ref decl, header, ref typarams, ref body) => {
                 self.head("")?;
                 self.print_fn(
                     decl,
-                    unsafety,
-                    constness.node,
-                    abi,
+                    header,
                     Some(item.ident),
                     typarams,
                     &item.vis
@@ -1582,9 +1578,7 @@ impl<'a> State<'a> {
                             vis: &ast::Visibility)
                             -> io::Result<()> {
         self.print_fn(&m.decl,
-                      m.unsafety,
-                      m.constness.node,
-                      m.abi,
+                      m.header,
                       Some(ident),
                       &generics,
                       vis)
@@ -2740,13 +2734,11 @@ impl<'a> State<'a> {
 
     pub fn print_fn(&mut self,
                     decl: &ast::FnDecl,
-                    unsafety: ast::Unsafety,
-                    constness: ast::Constness,
-                    abi: abi::Abi,
+                    header: ast::FnHeader,
                     name: Option<ast::Ident>,
                     generics: &ast::Generics,
                     vis: &ast::Visibility) -> io::Result<()> {
-        self.print_fn_header_info(unsafety, constness, abi, vis)?;
+        self.print_fn_header_info(header, vis)?;
 
         if let Some(name) = name {
             self.nbsp()?;
@@ -3058,9 +3050,7 @@ impl<'a> State<'a> {
             span: syntax_pos::DUMMY_SP,
         };
         self.print_fn(decl,
-                      unsafety,
-                      ast::Constness::NotConst,
-                      abi,
+                      ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
                       name,
                       &generics,
                       &codemap::dummy_spanned(ast::VisibilityKind::Inherited))?;
@@ -3123,22 +3113,25 @@ impl<'a> State<'a> {
     }
 
     pub fn print_fn_header_info(&mut self,
-                                unsafety: ast::Unsafety,
-                                constness: ast::Constness,
-                                abi: Abi,
+                                header: ast::FnHeader,
                                 vis: &ast::Visibility) -> io::Result<()> {
         self.s.word(&visibility_qualified(vis, ""))?;
 
-        match constness {
+        match header.constness.node {
             ast::Constness::NotConst => {}
             ast::Constness::Const => self.word_nbsp("const")?
         }
 
-        self.print_unsafety(unsafety)?;
+        match header.asyncness {
+            ast::IsAsync::NotAsync => {}
+            ast::IsAsync::Async => self.word_nbsp("async")?
+        }
+
+        self.print_unsafety(header.unsafety)?;
 
-        if abi != Abi::Rust {
+        if header.abi != Abi::Rust {
             self.word_nbsp("extern")?;
-            self.word_nbsp(&abi.to_string())?;
+            self.word_nbsp(&header.abi.to_string())?;
         }
 
         self.s.word("fn")
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index f896fa351b0..cfb29f562d7 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -124,24 +124,30 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
 
         if is_test_fn(&self.cx, &i) || is_bench_fn(&self.cx, &i) {
             match i.node {
-                ast::ItemKind::Fn(_, ast::Unsafety::Unsafe, _, _, _, _) => {
-                    let diag = self.cx.span_diagnostic;
-                    diag.span_fatal(i.span, "unsafe functions cannot be used for tests").raise();
-                }
-                _ => {
-                    debug!("this is a test function");
-                    let test = Test {
-                        span: i.span,
-                        path: self.cx.path.clone(),
-                        bench: is_bench_fn(&self.cx, &i),
-                        ignore: is_ignored(&i),
-                        should_panic: should_panic(&i, &self.cx),
-                        allow_fail: is_allowed_fail(&i),
-                    };
-                    self.cx.testfns.push(test);
-                    self.tests.push(i.ident);
+                ast::ItemKind::Fn(_, header, _, _) => {
+                    if header.unsafety == ast::Unsafety::Unsafe {
+                        let diag = self.cx.span_diagnostic;
+                        diag.span_fatal(i.span, "unsafe functions cannot be used for tests").raise();
+                    }
+                    if header.asyncness == ast::IsAsync::Async {
+                        let diag = self.cx.span_diagnostic;
+                        diag.span_fatal(i.span, "async functions cannot be used for tests").raise();
+                    }
                 }
+                _ => {},
             }
+
+            debug!("this is a test function");
+            let test = Test {
+                span: i.span,
+                path: self.cx.path.clone(),
+                bench: is_bench_fn(&self.cx, &i),
+                ignore: is_ignored(&i),
+                should_panic: should_panic(&i, &self.cx),
+                allow_fail: is_allowed_fail(&i),
+            };
+            self.cx.testfns.push(test);
+            self.tests.push(i.ident);
         }
 
         let mut item = i.into_inner();
@@ -338,7 +344,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     fn has_test_signature(_cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
         let has_should_panic_attr = attr::contains_name(&i.attrs, "should_panic");
         match i.node {
-            ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
+            ast::ItemKind::Fn(ref decl, _, ref generics, _) => {
                 // If the termination trait is active, the compiler will check that the output
                 // type implements the `Termination` trait as `libtest` enforces that.
                 let has_output = match decl.output {
@@ -396,7 +402,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
 
     fn has_bench_signature(_cx: &TestCtxt, i: &ast::Item) -> bool {
         match i.node {
-            ast::ItemKind::Fn(ref decl, _, _, _, _, _) => {
+            ast::ItemKind::Fn(ref decl, _, _, _) => {
                 // NB: inadequate check, but we're running
                 // well before resolve, can't get too deep.
                 decl.inputs.len() == 1
@@ -537,9 +543,7 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
     let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
     let main_body = ecx.block(sp, vec![call_test_main]);
     let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty)),
-                           ast::Unsafety::Normal,
-                           dummy_spanned(ast::Constness::NotConst),
-                           ::rustc_target::spec::abi::Abi::Rust,
+                           ast::FnHeader::default(),
                            ast::Generics::default(),
                            main_body);
     P(ast::Item {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 613f1a4f113..3df96ff07c5 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -23,17 +23,15 @@
 //! instance, a walker looking for item names in a module will miss all of
 //! those that are created by the expansion of a macro.
 
-use rustc_target::spec::abi::Abi;
 use ast::*;
 use syntax_pos::Span;
-use codemap::Spanned;
 use parse::token::Token;
 use tokenstream::{TokenTree, TokenStream};
 
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum FnKind<'a> {
     /// fn foo() or extern "Abi" fn foo()
-    ItemFn(Ident, Unsafety, Spanned<Constness>, Abi, &'a Visibility, &'a Block),
+    ItemFn(Ident, FnHeader, &'a Visibility, &'a Block),
 
     /// fn foo(&self)
     Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
@@ -235,10 +233,10 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_ty(typ);
             visitor.visit_expr(expr);
         }
-        ItemKind::Fn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
+        ItemKind::Fn(ref declaration, header, ref generics, ref body) => {
             visitor.visit_generics(generics);
-            visitor.visit_fn(FnKind::ItemFn(item.ident, unsafety,
-                                            constness, abi, &item.vis, body),
+            visitor.visit_fn(FnKind::ItemFn(item.ident, header, 
+                                            &item.vis, body),
                              declaration,
                              item.span,
                              item.id)
@@ -544,7 +542,7 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl
     where V: Visitor<'a>,
 {
     match kind {
-        FnKind::ItemFn(_, _, _, _, _, body) => {
+        FnKind::ItemFn(_, _, _, body) => {
             walk_fn_decl(visitor, declaration);
             visitor.visit_block(body);
         }
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 672726d1475..3ea0eb8bbd8 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -197,7 +197,7 @@ use syntax::ast::{VariantData, GenericParamKind, GenericArg};
 use syntax::attr;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::codemap::{self, dummy_spanned, respan};
+use syntax::codemap::{self, respan};
 use syntax::util::move_map::MoveMap;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
@@ -971,10 +971,10 @@ impl<'a> MethodDef<'a> {
             defaultness: ast::Defaultness::Final,
             ident: method_ident,
             node: ast::ImplItemKind::Method(ast::MethodSig {
-                                                abi,
-                                                unsafety,
-                                                constness:
-                                                    dummy_spanned(ast::Constness::NotConst),
+                                                header: ast::FnHeader {
+                                                    unsafety, abi,
+                                                    ..ast::FnHeader::default()
+                                                },
                                                 decl: fn_decl,
                                             },
                                             body_block),