diff --git a/src/Cargo.lock b/src/Cargo.lock index 40ec413c90a23..e4da1c07eabfa 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -190,13 +190,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo" -version = "0.29.0" +version = "0.28.0" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crates-io 0.17.0", + "crates-io 0.16.0", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -305,12 +305,12 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.202" +version = "0.0.200" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", - "clippy_lints 0.0.202", + "clippy_lints 0.0.200", "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -328,7 +328,6 @@ version = "0.2.0" [[package]] name = "clippy_lints" version = "0.0.200" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -348,7 +347,8 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.0.202" +version = "0.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -474,7 +474,7 @@ dependencies = [ [[package]] name = "crates-io" -version = "0.17.0" +version = "0.16.0" dependencies = [ "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1660,7 +1660,7 @@ dependencies = [ name = "rls" version = "0.128.0" dependencies = [ - "cargo 0.29.0", + "cargo 0.28.0", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.200 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1676,7 +1676,7 @@ dependencies = [ "rls-analysis 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-rustc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-nightly 0.7.0", @@ -1684,7 +1684,6 @@ dependencies = [ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1718,7 +1717,7 @@ dependencies = [ [[package]] name = "rls-rustc" -version = "0.3.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3158,7 +3157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-analysis 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da9794cd1f80f2cb888c00641a32f9855d0226c954ee31cef145784914c7142e" "checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2" "checksum rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd20763e1c60ae8945384c8a8fa4ac44f8afa7b0a817511f5e8927e5d24f988" -"checksum rls-rustc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ed5342b2bbbe8663c04600af506c8902b6b4d3e627b006eb1bd65aa14805f4d" +"checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb" "checksum rustc-ap-rustc_cratesio_shim 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7374a2b466e6e3ce489e045302e304849355faf7fd033d4d95e6e86e48c313b4" diff --git a/src/doc/book b/src/doc/book index 36d65d00164d1..f51127530d46b 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 36d65d00164d1750f6fa7f8b0f52dabc3fea500b +Subproject commit f51127530d46b9acbf4747c859da185e771cfcf3 diff --git a/src/libcore/future.rs b/src/libcore/future.rs new file mode 100644 index 0000000000000..3bead5aa2d998 --- /dev/null +++ b/src/libcore/future.rs @@ -0,0 +1,6 @@ +//! Futures and supporting APIs. +#![unstable(feature = "async_await", issue = "50547")] + +/// The Future trait. +#[unstable(feature = "async_await", issue = "50547")] +pub trait Future { } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 2121bc4438056..73d627d1e3a59 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -191,10 +191,11 @@ pub mod ascii; pub mod sync; pub mod cell; pub mod char; -pub mod panic; -pub mod panicking; +pub mod future; pub mod iter; pub mod option; +pub mod panic; +pub mod panicking; pub mod raw; pub mod result; diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index a95f05227fb8b..6016f736952ad 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -97,3 +97,16 @@ pub struct TraitObject { pub data: *mut (), pub vtable: *mut (), } + +/// An adapter from a generator to a future. +/// +/// This is a permanently unstable API used by the compiler. You should not +/// depend on it. +#[allow(missing_debug_implementations, dead_code)] +#[unstable(feature = "gen_future", issue = "50547")] +pub struct GenFuture, R>(pub G); + +#[unstable(feature = "gen_future", issue = "50547")] +impl ::future::Future for GenFuture where + G: ::ops::Generator +{ } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 2ef022cecdf49..c65a85a8357fe 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, Name, Attribute}; use syntax_pos::Span; use hir::*; @@ -55,7 +54,7 @@ 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]), + ItemFn(Name, &'a Generics, FnHeader, &'a Visibility, &'a [Attribute]), /// fn foo(&self) Method(Name, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]), @@ -466,12 +465,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 d20cea8331fdd..ff9c925907c1f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -296,6 +296,14 @@ enum AnonymousLifetimeMode { PassThrough, } +trait FnRetTransform { + fn lower(&self, ctx: &mut LoweringContext, output: &FunctionRetTy, impl_trait_context: ImplTraitContext) -> hir::FunctionRetTy; +} + +struct NonAsyncRet; +struct AsyncClosureRet; +struct AsyncFunctionRet; + impl<'a> LoweringContext<'a> { fn lower_crate(mut self, c: &Crate) -> hir::Crate { /// Full-crate AST visitor that inserts into a fresh @@ -817,6 +825,50 @@ impl<'a> LoweringContext<'a> { result } + // Takes the body of an async function/closure, or an async block, and + // lowers it to a generator wrapped in a ::std::raw::GenFuture adapter. + // + // This makes it evaluate to a Future. + // + // For example, this: + // async { ... } + // Becomes: + // + // ::std::raw::GenFuture(|| { ... }) + // + // TODO: Visit body and make sure it contains no bare `yield` statements. + fn make_async_expr(&mut self, body: hir::Expr) -> hir::Expr { + let span = body.span; + + // Construct a generator around body + let generator = { + let decl = P(hir::FnDecl { + inputs: hir_vec![], + output: hir::DefaultReturn(span), + variadic: false, + has_implicit_self: false, + }); + let body_id = { + let prev = mem::replace(&mut self.is_generator, true); + let r = self.record_body(body, None); + self.is_generator = prev; + r + }; + let LoweredNodeId { node_id, hir_id } = self.next_id(); + hir::Expr { + id: node_id, + node: hir::ExprClosure(hir::CaptureByValue, decl, body_id, span, + Some(hir::GeneratorMovability::Static)), + attrs: ThinVec::new(), + span, hir_id, + } + }; + + let gen_future = self.expr_std_path(span, &["raw", "GenFuture"], ThinVec::new()); + self.expr_call(span, P(gen_future), hir_vec![generator]) + } + + fn lower_body(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId where F: FnOnce(&mut LoweringContext) -> hir::Expr, @@ -1050,7 +1102,7 @@ impl<'a> LoweringContext<'a> { ), unsafety: this.lower_unsafety(f.unsafety), abi: f.abi, - decl: this.lower_fn_decl(&f.decl, None, false), + decl: this.lower_fn_decl(&f.decl, None, false, &NonAsyncRet), arg_names: this.lower_fn_args_to_names(&f.decl), })) }, @@ -1729,7 +1781,121 @@ impl<'a> LoweringContext<'a> { decl: &FnDecl, fn_def_id: Option, impl_trait_return_allow: bool, + fn_ret_transform: &FnRetTransform, ) -> P { + // For non async functions, the return type is lowered in a straightforward way + impl FnRetTransform for NonAsyncRet { + fn lower(&self, ctx: &mut LoweringContext, output: &FunctionRetTy, impl_trait_context: ImplTraitContext) -> hir::FunctionRetTy { + match output { + FunctionRetTy::Ty(ty) => hir::Return(ctx.lower_ty(ty, impl_trait_context)), + FunctionRetTy::Default(span) => hir::DefaultReturn(*span), + } + } + } + + // For async closures: + // - If the return type is omitted, a straightforward lowering is performed + // - If the return type is explicit, given a return type T, it is lowered to + // ::std::raw::GenFuture<_, T> + impl FnRetTransform for AsyncClosureRet { + fn lower(&self, ctx: &mut LoweringContext, output: &FunctionRetTy, impl_trait_context: ImplTraitContext) -> hir::FunctionRetTy { + match output { + FunctionRetTy::Ty(ty) => { + let inner_ty = ctx.lower_ty(ty, impl_trait_context); + let span = inner_ty.span; + let hir::Path { def, segments, .. } = ctx.std_path(span, &["raw", "GenFuture"], false); + let LoweredNodeId { node_id, hir_id } = ctx.next_id(); + let gen_future_path = hir::Path { + segments: segments.map_slice(|mut v| { + v.last_mut().unwrap().parameters = Some(P(hir::PathParameters { + lifetimes: hir_vec![], + bindings: hir_vec![], + types: hir_vec![ + P(hir::Ty { + id: node_id, + node: hir::TyInfer, + hir_id, span, + }), + inner_ty, + ], + parenthesized: false, + })); + v + }), + def, span + }; + + let LoweredNodeId { node_id, hir_id } = ctx.next_id(); + hir::Return(P(hir::Ty { + id: node_id, + node: hir::TyPath(hir::QPath::Resolved(None, P(gen_future_path))), + hir_id, span, + })) + } + FunctionRetTy::Default(span) => hir::DefaultReturn(*span), + } + } + } + + // For async functions the return type is lowered to impl ::std::future::Future + impl FnRetTransform for AsyncFunctionRet { + fn lower(&self, ctx: &mut LoweringContext, output: &FunctionRetTy, impl_trait_context: ImplTraitContext) -> hir::FunctionRetTy { + let inner_ty = match output { + FunctionRetTy::Ty(ty) => ctx.lower_ty(ty, impl_trait_context), + FunctionRetTy::Default(span) => { + let LoweredNodeId { node_id, hir_id } = ctx.next_id(); + P(hir::Ty { + id: node_id, + hir_id: hir_id, + node: hir::TyTup(hir_vec![]), + span: *span, + }) + } + }; + let span = inner_ty.span; + let hir::Path { def, segments, .. } = ctx.std_path(span, &["future", "Future"], false); + let future_path = hir::Path { + segments: segments.map_slice(|mut v| { + v.last_mut().unwrap().parameters = Some(P(hir::PathParameters { + lifetimes: hir_vec![], + types: hir_vec![], + bindings: hir_vec![hir::TypeBinding { + name: ctx.str_to_ident("Output"), + ty: inner_ty, + id: ctx.next_id().node_id, + span, + }], + parenthesized: false, + })); + v + }), + def, span + }; + let LoweredNodeId { hir_id, node_id } = ctx.next_id(); + hir::Return(P(hir::Ty { + id: node_id, + node: hir::TyImplTraitExistential(hir::ExistTy { + generics: hir::Generics::empty(), + bounds: hir_vec![hir::TyParamBound::TraitTyParamBound(hir::PolyTraitRef { + trait_ref: hir::TraitRef { + path: future_path, + ref_id: ctx.next_id().node_id, + }, + bound_generic_params: hir_vec![], + span, + }, hir::TraitBoundModifier::None)], + }, hir_vec![]), + hir_id, span, + })) + } + } + + let output_impl_trait_context = if fn_def_id.is_some() && impl_trait_return_allow { + ImplTraitContext::Existential + } else { + ImplTraitContext::Disallowed + }; + // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some, // then impl Trait arguments are lowered into generic parameters on the given // fn_def_id, otherwise impl Trait is disallowed. (for now) @@ -1748,15 +1914,7 @@ impl<'a> LoweringContext<'a> { } }) .collect(), - output: match decl.output { - FunctionRetTy::Ty(ref ty) => match fn_def_id { - Some(_) if impl_trait_return_allow => { - hir::Return(self.lower_ty(ty, ImplTraitContext::Existential)) - } - _ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)), - }, - FunctionRetTy::Default(span) => hir::DefaultReturn(span), - }, + output: fn_ret_transform.lower(self, &decl.output, output_impl_trait_context), variadic: decl.variadic, has_implicit_self: decl.inputs.get(0).map_or(false, |arg| match arg.ty.node { TyKind::ImplicitSelf => true, @@ -2194,25 +2352,30 @@ 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| { let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) + let expr = this.expr_block(body, ThinVec::new()); + if header.asyncness == IsAsync::Async { + this.make_async_expr(expr) + } else { expr } }); + let fn_ret_transform: &FnRetTransform = match header.asyncness { + IsAsync::Async => &AsyncFunctionRet, + IsAsync::NotAsync => &NonAsyncRet, + }; let (generics, fn_decl) = this.add_in_band_defs( generics, fn_def_id, AnonymousLifetimeMode::PassThrough, - |this| this.lower_fn_decl(decl, Some(fn_def_id), true), + |this| this.lower_fn_decl(decl, Some(fn_def_id), true, fn_ret_transform), ); hir::ItemFn( fn_decl, - this.lower_unsafety(unsafety), - this.lower_constness(constness), - abi, + this.lower_fn_header(header), generics, body_id, ) @@ -2492,7 +2655,10 @@ impl<'a> LoweringContext<'a> { TraitItemKind::Method(ref sig, Some(ref body)) => { let body_id = this.lower_body(Some(&sig.decl), |this| { let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) + let expr = this.expr_block(body, ThinVec::new()); + if sig.header.asyncness == IsAsync::Async { + this.make_async_expr(expr) + } else { expr } }); this.add_in_band_defs( @@ -2575,7 +2741,10 @@ impl<'a> LoweringContext<'a> { ImplItemKind::Method(ref sig, ref body) => { let body_id = this.lower_body(Some(&sig.decl), |this| { let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) + let e = this.expr_block(body, ThinVec::new()); + if sig.header.asyncness == IsAsync::Async { + this.make_async_expr(e) + } else { e } }); let impl_trait_return_allow = !this.is_in_trait_impl; @@ -2723,7 +2892,7 @@ impl<'a> LoweringContext<'a> { |this| { ( // Disallow impl Trait in foreign items - this.lower_fn_decl(fdec, None, false), + this.lower_fn_decl(fdec, None, false, &NonAsyncRet), this.lower_fn_args_to_names(fdec), ) }, @@ -2749,11 +2918,13 @@ impl<'a> LoweringContext<'a> { fn_def_id: DefId, impl_trait_return_allow: bool, ) -> hir::MethodSig { + let fn_ret_transform: &FnRetTransform = match sig.header.asyncness { + IsAsync::Async => &AsyncFunctionRet, + IsAsync::NotAsync => &NonAsyncRet, + }; hir::MethodSig { - abi: sig.abi, - unsafety: self.lower_unsafety(sig.unsafety), - constness: self.lower_constness(sig.constness), - decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow), + header: self.lower_fn_header(sig.header), + decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, fn_ret_transform), } } @@ -2764,6 +2935,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, @@ -2778,6 +2958,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, @@ -3062,14 +3249,16 @@ impl<'a> LoweringContext<'a> { arms.iter().map(|x| self.lower_arm(x)).collect(), hir::MatchSource::Normal, ), - ExprKind::Closure(capture_clause, movability, ref decl, ref body, fn_decl_span) => { + ExprKind::Closure(capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span) => { self.with_new_scopes(|this| { this.with_parent_def(e.id, |this| { let mut is_generator = false; let body_id = this.lower_body(Some(decl), |this| { let e = this.lower_expr(body); is_generator = this.is_generator; - e + if asyncness == IsAsync::Async { + this.make_async_expr(e) + } else { e } }); let generator_option = if is_generator { if !decl.inputs.is_empty() { @@ -3096,9 +3285,13 @@ impl<'a> LoweringContext<'a> { } None }; + let fn_ret_transform: &FnRetTransform = match asyncness { + IsAsync::Async => &AsyncClosureRet, + IsAsync::NotAsync => &NonAsyncRet, + }; hir::ExprClosure( this.lower_capture_clause(capture_clause), - this.lower_fn_decl(decl, None, false), + this.lower_fn_decl(decl, None, false, fn_ret_transform), body_id, fn_decl_span, generator_option, @@ -3107,9 +3300,15 @@ impl<'a> LoweringContext<'a> { }) } ExprKind::Block(ref blk, opt_label) => { - hir::ExprBlock(self.lower_block(blk, - opt_label.is_some()), - self.lower_label(opt_label)) + let blk = self.lower_block(blk, + opt_label.is_some()); + let opt_label = self.lower_label(opt_label); + hir::ExprBlock(blk, opt_label) + } + ExprKind::Async(ref blk) => { + let blk = self.lower_block(blk, false); + let expr = self.expr(blk.span, hir::ExprBlock(blk, None), ThinVec::new()); + return self.make_async_expr(expr); } ExprKind::Assign(ref el, ref er) => { hir::ExprAssign(P(self.lower_expr(el)), P(self.lower_expr(er))) diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 362c0bf07f73b..f665ced3dbcf1 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 951bb6ad1501b..59c4166b7eaa5 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -176,7 +176,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 7db77a3e4afa5..d5f1fb046388a 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1558,9 +1558,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, } @@ -1787,7 +1785,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, @@ -2063,6 +2067,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. @@ -2082,7 +2105,7 @@ pub enum Item_ { /// A `const` item ItemConst(P, BodyId), /// A function declaration - ItemFn(P, Unsafety, Constness, Abi, Generics, BodyId), + ItemFn(P, FnHeader, Generics, BodyId), /// A module ItemMod(Mod), /// An external module @@ -2144,7 +2167,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 8173ec48045c3..dad6db67237fb 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -446,9 +446,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, @@ -585,12 +583,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, @@ -887,9 +883,7 @@ impl<'a> State<'a> { body_id: Option) -> io::Result<()> { self.print_fn(&m.decl, - m.unsafety, - m.constness, - m.abi, + m.header, Some(name), generics, vis, @@ -1924,16 +1918,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, generics: &hir::Generics, vis: &hir::Visibility, arg_names: &[Spanned], body_id: Option) -> 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()?; @@ -2189,9 +2181,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, @@ -2262,22 +2255,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 21c1af919de9a..80c3613b2b696 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -260,9 +260,7 @@ impl_stable_hash_for!(struct hir::MutTy { }); impl_stable_hash_for!(struct hir::MethodSig { - unsafety, - constness, - abi, + header, decl }); @@ -273,6 +271,13 @@ impl_stable_hash_for!(struct hir::TypeBinding { span }); +impl_stable_hash_for!(struct hir::FnHeader { + unsafety, + constness, + asyncness, + abi +}); + impl<'a> HashStable> for hir::Ty { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, @@ -877,7 +882,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), @@ -1078,6 +1083,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 249651ef65da0..bddd1ecc9654f 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -227,8 +227,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 966000ccd908a..ad07cf4d2f23d 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -474,7 +474,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 497d5fdcac702..e0c3a6a429f2e 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 f1ad14237eec2..5b42bec8b2a02 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -706,8 +706,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)) @@ -716,8 +716,8 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector { 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)) @@ -726,8 +726,8 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector { 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 651a2e187f6b4..bfbabc4cf0b1b 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -282,9 +282,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 5951fd478d89f..4c3e0fe39ded0 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -258,12 +258,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") } } @@ -274,7 +274,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 ab30ff7f072b7..da8c2374aa603 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)), }; @@ -1231,13 +1231,13 @@ 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, _, ref generics, _) => { + hir::ItemFn(_, header, ref generics, _) => { let has_tps = generics.ty_params().next().is_some(); let needs_inline = (has_tps || 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 fc3764e4f49a5..0eacb2034cdf9 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -379,10 +379,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 4f239a0868ebf..d55825413e03d 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_resolve/lib.rs b/src/librustc_resolve/lib.rs index 84b17f155a0e9..4c4caf4309215 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -790,7 +790,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { FnKind::Method(_, _, _, _) => { TraitOrImplItemRibKind } - FnKind::Closure(_) => ClosureRibKind(node_id), + FnKind::Closure(..) => ClosureRibKind(node_id), }; // Create a value rib for the function. @@ -816,7 +816,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { FnKind::Method(.., body) => { self.visit_block(body); } - FnKind::Closure(body) => { + FnKind::Closure(_, body) => { self.visit_expr(body); } }; diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 279ee403cc625..3a8e2031ca663 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1549,7 +1549,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc } } } - ast::ExprKind::Closure(_, _, ref decl, ref body, _fn_decl_span) => { + ast::ExprKind::Closure(_, _, _, ref decl, ref body, _fn_decl_span) => { let mut id = String::from("$"); id.push_str(&ex.id.to_string()); diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index e3545e8f1a9b8..0adbcc9a8103e 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 "); @@ -925,15 +928,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 d0d147b8e85cd..12e93ce00fe7f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1146,13 +1146,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 f112f3ca2ae53..4c0cbfc954fd7 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -181,9 +181,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 d4c1ba63a8c98..d44eb52dc9138 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -19,8 +19,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, Ident}; use syntax::attr; use syntax::codemap::{dummy_spanned, Spanned}; @@ -1901,10 +1901,8 @@ impl<'a, 'tcx> Clean 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 for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) { @@ -1915,28 +1913,23 @@ impl<'a> Clean 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 for doctree::Function { @@ -1955,9 +1948,7 @@ impl Clean for doctree::Function { inner: FunctionItem(Function { decl, generics, - unsafety: self.unsafety, - constness: self.constness, - abi: self.abi, + header: self.header, }), } } @@ -2186,10 +2177,9 @@ impl Clean 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) => { @@ -2288,18 +2278,24 @@ impl<'tcx> Clean 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() + } }) } } @@ -3485,9 +3481,9 @@ impl Clean for hir::BareFnTy { }); BareFunctionDecl { unsafety: self.unsafety, + abi: self.abi, decl, generic_params, - abi: self.abi, } } } @@ -3775,7 +3771,7 @@ impl Clean> 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 @@ -3792,9 +3788,7 @@ impl Clean 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 f85a70a6d401f..127949df2797c 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, pub depr: Option, - 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/format.rs b/src/librustdoc/html/format.rs index 40dcd6e891fe8..fc397d0584009 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -39,6 +39,10 @@ pub struct UnsafetySpace(pub hir::Unsafety); /// with a space after it. #[derive(Copy, Clone)] pub struct ConstnessSpace(pub hir::Constness); +/// Similarly to VisSpace, this structure is used to render a function asyncness +/// with a space after it. +#[derive(Copy, Clone)] +pub struct AsyncSpace(pub hir::IsAsync); /// Similar to VisSpace, but used for mutability #[derive(Copy, Clone)] pub struct MutableSpace(pub clean::Mutability); @@ -962,6 +966,15 @@ impl fmt::Display for ConstnessSpace { } } +impl fmt::Display for AsyncSpace { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + hir::IsAsync::Async => write!(f, "async "), + hir::IsAsync::NotAsync => Ok(()), + } + } +} + impl fmt::Display for clean::Import { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 109765b671197..68345ab9857d6 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -62,13 +62,12 @@ 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; use fold::DocFolder; use html::escape::Escape; -use html::format::{ConstnessSpace}; +use html::format::{AsyncSpace, ConstnessSpace}; use html::format::{TyParamBounds, WhereClause, href, AbiSpace}; use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; use html::format::fmt_impl_for_trait_page; @@ -2423,7 +2422,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 => { "" } _ => "", @@ -2593,21 +2592,23 @@ fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, f: &clean::Function) -> fmt::Result { - let name_len = format!("{}{}{}{:#}fn {}{:#}", + let name_len = format!("{}{}{}{}{:#}fn {}{:#}", VisSpace(&it.visibility), - ConstnessSpace(f.constness), - UnsafetySpace(f.unsafety), - AbiSpace(f.abi), + ConstnessSpace(f.header.constness), + AsyncSpace(f.header.asyncness), + UnsafetySpace(f.header.unsafety), + AbiSpace(f.header.abi), it.name.as_ref().unwrap(), f.generics).len(); write!(w, "{}
", render_spotlight_traits(it)?)?;
     render_attributes(w, it)?;
     write!(w,
-           "{vis}{constness}{unsafety}{abi}fn {name}{generics}{decl}{where_clause}
", + "{vis}{constness}{asyncness}{unsafety}{abi}fn {name}{generics}{decl}{where_clause}", vis = VisSpace(&it.visibility), - constness = ConstnessSpace(f.constness), - unsafety = UnsafetySpace(f.unsafety), - abi = AbiSpace(f.abi), + constness = ConstnessSpace(f.header.constness), + asyncness = AsyncSpace(f.header.asyncness), + 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 }, @@ -3017,9 +3018,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, @@ -3044,9 +3043,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 { @@ -3058,9 +3057,9 @@ fn render_assoc_item(w: &mut fmt::Formatter, write!(w, "{}{}{}{}fn {name}\ {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, @@ -3078,12 +3077,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 8c2555c4b3de2..02974ce5893bb 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, } } @@ -458,9 +453,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/libstd/lib.rs b/src/libstd/lib.rs index f7d06852f2793..85d62ba0b6f98 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -242,6 +242,7 @@ #![feature(array_error_internals)] #![feature(ascii_ctype)] #![feature(asm)] +#![feature(async_await)] #![feature(attr_literals)] #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] @@ -390,6 +391,8 @@ pub use core::cmp; pub use core::convert; #[stable(feature = "rust1", since = "1.0.0")] pub use core::default; +#[unstable(feature = "async_await", issue = "50547")] +pub use core::future; #[stable(feature = "rust1", since = "1.0.0")] pub use core::hash; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c9843de547fb2..e2a95ec94e28e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -18,7 +18,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; @@ -947,7 +947,7 @@ impl Expr { /// Whether this expression would be valid somewhere that expects a value, for example, an `if` /// condition. pub fn returns(&self) -> bool { - if let ExprKind::Block(ref block, _) = self.node { + if let ExprKind::Block(ref block, ..) = self.node { match block.stmts.last().map(|last_stmt| &last_stmt.node) { // implicit return Some(&StmtKind::Expr(_)) => true, @@ -1027,6 +1027,7 @@ impl Expr { ExprKind::Match(..) => ExprPrecedence::Match, ExprKind::Closure(..) => ExprPrecedence::Closure, ExprKind::Block(..) => ExprPrecedence::Block, + ExprKind::Async(..) => ExprPrecedence::Async, ExprKind::Catch(..) => ExprPrecedence::Catch, ExprKind::Assign(..) => ExprPrecedence::Assign, ExprKind::AssignOp(..) => ExprPrecedence::AssignOp, @@ -1133,11 +1134,13 @@ pub enum ExprKind { /// A closure (for example, `move |a, b, c| a + b + c`) /// /// The final span is the span of the argument block `|...|` - Closure(CaptureBy, Movability, P, P, Span), + Closure(CaptureBy, IsAsync, Movability, P, P, Span), /// A block (`'label: { ... }`) Block(P, Option