diff options
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), |
