From 8300f51936149ec43eb063205e4d03c54a308f3c Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Sat, 23 Feb 2019 18:39:27 +0000 Subject: [PATCH] Deny `async fn` in 2015 edition Fix style issues and update diagnostic messages Update src/librustc_passes/diagnostics.rs Co-Authored-By: doctorn Deny nested `async fn` in Rust 2015 edition Deny nested `async fn` in Rust 2015 edition Deny nested `async fn` in Rust 2015 edition --- src/librustc/hir/lowering.rs | 10 ++-- src/librustc/hir/map/def_collector.rs | 10 ++-- src/librustc_passes/ast_validation.rs | 14 ++++- src/librustc_passes/diagnostics.rs | 12 ++++ src/librustc_resolve/lib.rs | 4 +- src/librustc_save_analysis/sig.rs | 4 +- src/libsyntax/ast.rs | 4 +- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/feature_gate.rs | 2 +- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/parse/parser.rs | 39 +++++++++---- src/libsyntax/print/pprust.rs | 4 +- src/libsyntax/visit.rs | 15 +++-- src/libsyntax_ext/test.rs | 2 +- .../editions/edition-deny-async-fns-2015.rs | 34 +++++++++++ .../edition-deny-async-fns-2015.stderr | 58 +++++++++++++++++++ .../feature-gate-async-await-2015-edition.rs | 3 +- ...ature-gate-async-await-2015-edition.stderr | 16 +++-- .../recursive-async-impl-trait-type.rs | 11 ++++ .../recursive-async-impl-trait-type.stderr | 11 ++++ .../impl-trait/recursive-impl-trait-type.rs | 6 +- .../recursive-impl-trait-type.stderr | 14 +---- 22 files changed, 215 insertions(+), 62 deletions(-) create mode 100644 src/test/ui/editions/edition-deny-async-fns-2015.rs create mode 100644 src/test/ui/editions/edition-deny-async-fns-2015.stderr create mode 100644 src/test/ui/impl-trait/recursive-async-impl-trait-type.rs create mode 100644 src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f6b68682886e7..f65bd255ba66e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2906,7 +2906,7 @@ impl<'a> LoweringContext<'a> { // `impl Future` here because lower_body // only cares about the input argument patterns in the function // declaration (decl), not the return types. - let body_id = this.lower_async_body(decl, header.asyncness, body); + let body_id = this.lower_async_body(decl, header.asyncness.node, body); let (generics, fn_decl) = this.add_in_band_defs( generics, @@ -2916,7 +2916,7 @@ impl<'a> LoweringContext<'a> { decl, Some((fn_def_id, idty)), true, - header.asyncness.opt_return_id() + header.asyncness.node.opt_return_id() ), ); @@ -3410,14 +3410,14 @@ impl<'a> LoweringContext<'a> { ) } ImplItemKind::Method(ref sig, ref body) => { - let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness, body); + let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body); let impl_trait_return_allow = !self.is_in_trait_impl; let (generics, sig) = self.lower_method_sig( &i.generics, sig, impl_item_def_id, impl_trait_return_allow, - sig.header.asyncness.opt_return_id(), + sig.header.asyncness.node.opt_return_id(), ); (generics, hir::ImplItemKind::Method(sig, body_id)) } @@ -3637,7 +3637,7 @@ 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), + asyncness: self.lower_asyncness(h.asyncness.node), constness: self.lower_constness(h.constness), abi: h.abi, } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 72aa9570cc2ff..12760f8b9828b 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -73,7 +73,7 @@ impl<'a> DefCollector<'a> { decl: &'a FnDecl, body: &'a Block, ) { - let (closure_id, return_impl_trait_id) = match header.asyncness { + let (closure_id, return_impl_trait_id) = match header.asyncness.node { IsAsync::Async { closure_id, return_impl_trait_id, @@ -129,10 +129,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } ItemKind::Fn( ref decl, - ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, + ref header, ref generics, ref body, - ) => { + ) if header.asyncness.node.is_async() => { return self.visit_async_fn( i.id, i.ident.name, @@ -242,9 +242,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { let def_data = match ii.node { ImplItemKind::Method(MethodSig { - header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, + ref header, ref decl, - }, ref body) => { + }, ref body) if header.asyncness.node.is_async() => { return self.visit_async_fn( ii.id, ii.ident.name, diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 606ae27412832..f96fc3b897f80 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -463,7 +463,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility(&impl_item.vis, None); if let ImplItemKind::Method(ref sig, _) = impl_item.node { self.check_trait_fn_not_const(sig.header.constness); - self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness); + self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node); } } } @@ -482,9 +482,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .note("only trait implementations may be annotated with default").emit(); } } - ItemKind::Fn(_, header, ref generics, _) => { + ItemKind::Fn(_, ref header, ref generics, _) => { // We currently do not permit const generics in `const fn`, as // this is tantamount to allowing compile-time dependent typing. + self.visit_fn_header(header); if header.constness.node == Constness::Const { // Look for const generics and error if we find any. for param in &generics.params { @@ -535,7 +536,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_async(trait_item.span, sig.header.asyncness); + self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node); self.check_trait_fn_not_const(sig.header.constness); if block.is_none() { self.check_decl_no_pat(&sig.decl, |span, mut_ident| { @@ -702,6 +703,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \ the relevant `fold_*()` method in `PlaceholderExpander`?"); } + + fn visit_fn_header(&mut self, header: &'a FnHeader) { + if header.asyncness.node.is_async() && self.session.rust_2015() { + struct_span_err!(self.session, header.asyncness.span, E0670, + "`async fn` is not permitted in the 2015 edition").emit(); + } + } } pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) { diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 19d4d3aeb0f65..e3c6b16703a4a 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -310,6 +310,18 @@ loop { break; } ``` +"##, + +E0670: r##" +Rust 2015 does not permit the use of `async fn`. + +Example of erroneous code: + +```compile_fail,E0670 +async fn foo() {} +``` + +Switch to the Rust 2018 edition to use `async fn`. "## } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 1a7744786d80e..3993964bd9db9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -806,9 +806,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { debug!("(resolving function) entering function"); let (rib_kind, asyncness) = match function_kind { FnKind::ItemFn(_, ref header, ..) => - (ItemRibKind, header.asyncness), + (ItemRibKind, header.asyncness.node), FnKind::Method(_, ref sig, _, _) => - (TraitOrImplItemRibKind, sig.header.asyncness), + (TraitOrImplItemRibKind, sig.header.asyncness.node), FnKind::Closure(_) => // Async closures aren't resolved through `visit_fn`-- they're // processed separately diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 50a335bf90877..52f3a20777021 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -378,7 +378,7 @@ impl Sig for ast::Item { if header.constness.node == ast::Constness::Const { text.push_str("const "); } - if header.asyncness.is_async() { + if header.asyncness.node.is_async() { text.push_str("async "); } if header.unsafety == ast::Unsafety::Unsafe { @@ -936,7 +936,7 @@ fn make_method_signature( if m.header.constness.node == ast::Constness::Const { text.push_str("const "); } - if m.header.asyncness.is_async() { + if m.header.asyncness.node.is_async() { text.push_str("async "); } if m.header.unsafety == ast::Unsafety::Unsafe { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9c4945d74dbfe..b6f9ae36da70c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2216,7 +2216,7 @@ impl Item { #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub struct FnHeader { pub unsafety: Unsafety, - pub asyncness: IsAsync, + pub asyncness: Spanned, pub constness: Spanned, pub abi: Abi, } @@ -2225,7 +2225,7 @@ impl Default for FnHeader { fn default() -> FnHeader { FnHeader { unsafety: Unsafety::Normal, - asyncness: IsAsync::NotAsync, + asyncness: dummy_spanned(IsAsync::NotAsync), constness: dummy_spanned(Constness::NotConst), abi: Abi::Rust, } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 27b0cfb163077..2f88749ace85e 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -1017,7 +1017,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)), ast::FnHeader { unsafety: ast::Unsafety::Normal, - asyncness: ast::IsAsync::NotAsync, + asyncness: dummy_spanned(ast::IsAsync::NotAsync), constness: dummy_spanned(ast::Constness::NotConst), abi: Abi::Rust, }, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d574b410ccc06..0f7ba041f9c08 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1894,7 +1894,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match fn_kind { FnKind::ItemFn(_, header, _, _) => { // Check for const fn and async fn declarations. - if header.asyncness.is_async() { + if header.asyncness.node.is_async() { gate_feature_post!(&self, async_await, span, "async fn is unstable"); } // Stability of const fn methods are covered in diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 86849f580d081..935142e8a2def 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -926,7 +926,7 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header; - vis.visit_asyncness(asyncness); + vis.visit_asyncness(&mut asyncness.node); } pub fn noop_visit_mod(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5a753e1f8c8a5..c257f05ae468e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5001,6 +5001,11 @@ impl<'a> Parser<'a> { ) } + fn is_async_fn(&mut self) -> bool { + self.token.is_keyword(keywords::Async) && + self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) + } + fn is_do_catch_block(&mut self) -> bool { self.token.is_keyword(keywords::Do) && self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) && @@ -5133,7 +5138,8 @@ impl<'a> Parser<'a> { !self.is_union_item() && !self.is_crate_vis() && !self.is_existential_type_decl() && - !self.is_auto_trait_item() { + !self.is_auto_trait_item() && + !self.is_async_fn() { let pth = self.parse_path(PathStyle::Expr)?; if !self.eat(&token::Not) { @@ -6346,7 +6352,7 @@ impl<'a> Parser<'a> { /// Parses an item-position function declaration. fn parse_item_fn(&mut self, unsafety: Unsafety, - asyncness: IsAsync, + asyncness: Spanned, constness: Spanned, abi: Abi) -> PResult<'a, ItemInfo> { @@ -6378,7 +6384,7 @@ impl<'a> Parser<'a> { -> PResult<'a, ( Spanned, Unsafety, - IsAsync, + Spanned, Abi )> { @@ -6386,6 +6392,7 @@ impl<'a> Parser<'a> { let const_span = self.prev_span; let unsafety = self.parse_unsafety(); let asyncness = self.parse_asyncness(); + let asyncness = respan(self.prev_span, asyncness); let (constness, unsafety, abi) = if is_const_fn { (respan(const_span, Constness::Const), unsafety, Abi::Rust) } else { @@ -7796,7 +7803,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, IsAsync::NotAsync), respan(fn_span, Constness::NotConst), abi)?; let prev_span = self.prev_span; @@ -7840,7 +7847,7 @@ impl<'a> Parser<'a> { self.bump(); let (ident, item_, extra_attrs) = self.parse_item_fn(unsafety, - IsAsync::NotAsync, + respan(const_span, IsAsync::NotAsync), respan(const_span, Constness::Const), Abi::Rust)?; let prev_span = self.prev_span; @@ -7888,14 +7895,15 @@ impl<'a> Parser<'a> { // ASYNC FUNCTION ITEM let unsafety = self.parse_unsafety(); self.expect_keyword(keywords::Async)?; + let async_span = self.prev_span; self.expect_keyword(keywords::Fn)?; let fn_span = self.prev_span; let (ident, item_, extra_attrs) = self.parse_item_fn(unsafety, - IsAsync::Async { + respan(async_span, IsAsync::Async { closure_id: ast::DUMMY_NODE_ID, return_impl_trait_id: ast::DUMMY_NODE_ID, - }, + }), respan(fn_span, Constness::NotConst), Abi::Rust)?; let prev_span = self.prev_span; @@ -7904,6 +7912,13 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); + if self.span.rust_2015() { + self.diagnostic().struct_span_err_with_code( + async_span, + "`async fn` is not permitted in the 2015 edition", + DiagnosticId::Error("E0670".into()) + ).emit(); + } return Ok(Some(item)); } if self.check_keyword(keywords::Unsafe) && @@ -7951,7 +7966,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, IsAsync::NotAsync), respan(fn_span, Constness::NotConst), Abi::Rust)?; let prev_span = self.prev_span; @@ -7977,7 +7992,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, IsAsync::NotAsync), respan(fn_span, Constness::NotConst), abi)?; let prev_span = self.prev_span; @@ -8244,7 +8259,8 @@ impl<'a> Parser<'a> { lo: Span, visibility: Visibility ) -> PResult<'a, Option>> { - if macros_allowed && self.token.is_path_start() { + if macros_allowed && self.token.is_path_start() && + !(self.is_async_fn() && self.span.rust_2015()) { // MACRO INVOCATION ITEM let prev_span = self.prev_span; @@ -8299,7 +8315,8 @@ impl<'a> Parser<'a> { fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>, at_end: &mut bool) -> PResult<'a, Option> { - if self.token.is_path_start() { + if self.token.is_path_start() && + !(self.is_async_fn() && self.span.rust_2015()) { let prev_span = self.prev_span; let lo = self.span; let pth = self.parse_path(PathStyle::Mod)?; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index dcf9815f6d1ba..d6265ebde1bbc 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -3195,7 +3195,7 @@ impl<'a> State<'a> { ast::Constness::Const => self.word_nbsp("const")? } - self.print_asyncness(header.asyncness)?; + self.print_asyncness(header.asyncness.node)?; self.print_unsafety(header.unsafety)?; if header.abi != Abi::Rust { @@ -3247,7 +3247,7 @@ mod tests { ast::FnHeader { unsafety: ast::Unsafety::Normal, constness: source_map::dummy_spanned(ast::Constness::NotConst), - asyncness: ast::IsAsync::NotAsync, + asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync), abi: Abi::Rust, }, abba_ident, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a002394c710fe..46d8d772e9321 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -22,7 +22,7 @@ use syntax_pos::Span; #[derive(Copy, Clone)] pub enum FnKind<'a> { /// fn foo() or extern "Abi" fn foo() - ItemFn(Ident, FnHeader, &'a Visibility, &'a Block), + ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block), /// fn foo(&self) Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block), @@ -149,6 +149,9 @@ pub trait Visitor<'ast>: Sized { fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) { walk_fn_ret_ty(self, ret_ty) } + fn visit_fn_header(&mut self, _header: &'ast FnHeader) { + // Nothing to do + } } #[macro_export] @@ -225,8 +228,9 @@ 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, header, ref generics, ref body) => { + ItemKind::Fn(ref declaration, ref header, ref generics, ref body) => { visitor.visit_generics(generics); + visitor.visit_fn_header(header); visitor.visit_fn(FnKind::ItemFn(item.ident, header, &item.vis, body), declaration, @@ -539,11 +543,13 @@ 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(_, header, _, body) => { + visitor.visit_fn_header(header); walk_fn_decl(visitor, declaration); visitor.visit_block(body); } - FnKind::Method(_, _, _, body) => { + FnKind::Method(_, sig, _, body) => { + visitor.visit_fn_header(&sig.header); walk_fn_decl(visitor, declaration); visitor.visit_block(body); } @@ -564,6 +570,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai walk_list!(visitor, visit_expr, default); } TraitItemKind::Method(ref sig, None) => { + visitor.visit_fn_header(&sig.header); walk_fn_decl(visitor, &sig.decl); } TraitItemKind::Method(ref sig, Some(ref body)) => { diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 371862465487b..f4b625f8ea2c8 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -257,7 +257,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { ); return false } - if header.asyncness.is_async() { + if header.asyncness.node.is_async() { sd.span_err( i.span, "async functions cannot be used for tests" diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.rs b/src/test/ui/editions/edition-deny-async-fns-2015.rs new file mode 100644 index 0000000000000..2105aa5835d0d --- /dev/null +++ b/src/test/ui/editions/edition-deny-async-fns-2015.rs @@ -0,0 +1,34 @@ +// edition:2015 + +#![feature(futures_api, async_await)] + +async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + +fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition + +async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition + async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition +} + +struct Foo {} + +impl Foo { + async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition +} + +trait Bar { + async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + //~^ ERROR trait fns cannot be declared `async` +} + +fn main() { + macro_rules! accept_item { ($x:item) => {} } + + accept_item! { + async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + } + + let inside_closure = || { + async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition + }; +} diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.stderr b/src/test/ui/editions/edition-deny-async-fns-2015.stderr new file mode 100644 index 0000000000000..1ad907aa7eb43 --- /dev/null +++ b/src/test/ui/editions/edition-deny-async-fns-2015.stderr @@ -0,0 +1,58 @@ +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:5:1 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:7:12 + | +LL | fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:10:5 + | +LL | async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:9:1 + | +LL | async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:32:9 + | +LL | async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:28:9 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:16:5 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0706]: trait fns cannot be declared `async` + --> $DIR/edition-deny-async-fns-2015.rs:20:5 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^^^^^^^^^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:20:5 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error: aborting due to 9 previous errors + +Some errors occurred: E0670, E0706. +For more information about an error, try `rustc --explain E0670`. diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs index 84dd1b9f814c2..b6ab8ae0a9bc7 100644 --- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs +++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs @@ -2,7 +2,8 @@ #![feature(futures_api)] -async fn foo() {} //~ ERROR async fn is unstable +async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + //~^ ERROR async fn is unstable fn main() { let _ = async {}; //~ ERROR cannot find struct, variant or union type `async` diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr index 450b2c42f119d..58051153e1f0d 100644 --- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr +++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr @@ -1,11 +1,17 @@ +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/feature-gate-async-await-2015-edition.rs:5:1 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + error[E0422]: cannot find struct, variant or union type `async` in this scope - --> $DIR/feature-gate-async-await-2015-edition.rs:8:13 + --> $DIR/feature-gate-async-await-2015-edition.rs:9:13 | LL | let _ = async {}; //~ ERROR cannot find struct, variant or union type `async` | ^^^^^ not found in this scope error[E0425]: cannot find value `async` in this scope - --> $DIR/feature-gate-async-await-2015-edition.rs:9:13 + --> $DIR/feature-gate-async-await-2015-edition.rs:10:13 | LL | let _ = async || { true }; //~ ERROR cannot find value `async` in this scope | ^^^^^ not found in this scope @@ -13,12 +19,12 @@ LL | let _ = async || { true }; //~ ERROR cannot find value `async` in this error[E0658]: async fn is unstable (see issue #50547) --> $DIR/feature-gate-async-await-2015-edition.rs:5:1 | -LL | async fn foo() {} //~ ERROR async fn is unstable +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition | ^^^^^^^^^^^^^^^^^ | = help: add #![feature(async_await)] to the crate attributes to enable -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -Some errors occurred: E0422, E0425, E0658. +Some errors occurred: E0422, E0425, E0658, E0670. For more information about an error, try `rustc --explain E0422`. diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs new file mode 100644 index 0000000000000..40642523be255 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs @@ -0,0 +1,11 @@ +// edition:2018 +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden when using `async` and `await`. + +#![feature(await_macro, async_await, futures_api, generators)] + +async fn recursive_async_function() -> () { //~ ERROR + await!(recursive_async_function()); +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr new file mode 100644 index 0000000000000..acdeabb2f9892 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr @@ -0,0 +1,11 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-async-impl-trait-type.rs:7:40 + | +LL | async fn recursive_async_function() -> () { //~ ERROR + | ^^ expands to self-referential type + | + = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-async-impl-trait-type.rs:7:43: 9:2 {impl std::future::Future, ()}]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-impl-trait-type.rs index facb191a37081..869876dc6a88a 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type.rs +++ b/src/test/ui/impl-trait/recursive-impl-trait-type.rs @@ -1,7 +1,7 @@ // Test that impl trait does not allow creating recursive types that are // otherwise forbidden. -#![feature(await_macro, async_await, futures_api, generators)] +#![feature(futures_api, generators)] fn option(i: i32) -> impl Sized { //~ ERROR if i < 0 { @@ -62,10 +62,6 @@ fn generator_hold() -> impl Sized { //~ ERROR } } -async fn recursive_async_function() -> () { //~ ERROR - await!(recursive_async_function()); -} - fn use_fn_ptr() -> impl Sized { // OK, error already reported fn_ptr() } diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr index 8a8789120577e..96494229fd339 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr @@ -95,15 +95,7 @@ LL | fn generator_hold() -> impl Sized { //~ ERROR = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:65:40 - | -LL | async fn recursive_async_function() -> () { //~ ERROR - | ^^ expands to self-referential type - | - = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-impl-trait-type.rs:65:43: 67:2 {impl std::future::Future, ()}]>` - -error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:73:26 + --> $DIR/recursive-impl-trait-type.rs:69:26 | LL | fn mutual_recursion() -> impl Sync { //~ ERROR | ^^^^^^^^^ expands to self-referential type @@ -111,13 +103,13 @@ LL | fn mutual_recursion() -> impl Sync { //~ ERROR = note: type resolves to itself error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:77:28 + --> $DIR/recursive-impl-trait-type.rs:73:28 | LL | fn mutual_recursion_b() -> impl Sized { //~ ERROR | ^^^^^^^^^^ expands to self-referential type | = note: type resolves to itself -error: aborting due to 15 previous errors +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0720`.