]> git.lizzy.rs Git - rust.git/commitdiff
Deny `async fn` in 2015 edition
authorNathan Corbyn <me@nathancorbyn.com>
Sat, 23 Feb 2019 18:39:27 +0000 (18:39 +0000)
committerNathan Corbyn <me@nathancorbyn.com>
Sun, 24 Feb 2019 16:33:12 +0000 (16:33 +0000)
Fix style issues and update diagnostic messages

Update src/librustc_passes/diagnostics.rs

Co-Authored-By: doctorn <me@nathancorbyn.com>
Deny nested `async fn` in Rust 2015 edition

Deny nested `async fn` in Rust 2015 edition

Deny nested `async fn` in Rust 2015 edition

22 files changed:
src/librustc/hir/lowering.rs
src/librustc/hir/map/def_collector.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/sig.rs
src/libsyntax/ast.rs
src/libsyntax/ext/build.rs
src/libsyntax/feature_gate.rs
src/libsyntax/mut_visit.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libsyntax_ext/test.rs
src/test/ui/editions/edition-deny-async-fns-2015.rs [new file with mode: 0644]
src/test/ui/editions/edition-deny-async-fns-2015.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs
src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
src/test/ui/impl-trait/recursive-async-impl-trait-type.rs [new file with mode: 0644]
src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr [new file with mode: 0644]
src/test/ui/impl-trait/recursive-impl-trait-type.rs
src/test/ui/impl-trait/recursive-impl-trait-type.stderr

index f6b68682886e713f115ac391f0f0f04f5cdfc691..f65bd255ba66ee7d1684d2abff5e4521cda72119 100644 (file)
@@ -2906,7 +2906,7 @@ fn lower_item_kind(
                     // `impl Future<Output = T>` 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 @@ fn lower_item_kind(
                             decl,
                             Some((fn_def_id, idty)),
                             true,
-                            header.asyncness.opt_return_id()
+                            header.asyncness.node.opt_return_id()
                         ),
                     );
 
@@ -3410,14 +3410,14 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
                 )
             }
             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 @@ fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto {
     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,
         }
index 72aa9570cc2ffa04f8025ec16e992677a65c5955..12760f8b9828b2372c40c6335d1a422bfa64775f 100644 (file)
@@ -73,7 +73,7 @@ fn visit_async_fn(
         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 @@ fn visit_item(&mut self, i: &'a Item) {
             }
             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 @@ fn visit_trait_item(&mut self, ti: &'a TraitItem) {
     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,
index 606ae2741283240a973bfb136ac36fc36b8a3114..f96fc3b897f80bc4e85d40d225f737ae1dd77885 100644 (file)
@@ -463,7 +463,7 @@ fn visit_item(&mut self, item: &'a Item) {
                     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 @@ fn visit_item(&mut self, item: &'a Item) {
                         .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 @@ fn visit_item(&mut self, item: &'a Item) {
                 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 @@ fn visit_mac(&mut self, mac: &Spanned<Mac_>) {
             .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) {
index 19d4d3aeb0f6530e06a0a724bb89c2cb0e52b4b6..e3c6b16703a4ac1a105fdc91812297d5168dff5d 100644 (file)
@@ -310,6 +310,18 @@ trait Foo {
     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`.
 "##
 }
 
index 1a7744786d80eefcd6cccc9462200d2b500ed9b3..3993964bd9db9a6628e5e508b5655f02ac9f91c0 100644 (file)
@@ -806,9 +806,9 @@ fn visit_fn(&mut self,
         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
index 50a335bf908776cf26eee6351e7f6e61af868e7d..52f3a2077702192a22ac8c8419b0145952cb665e 100644 (file)
@@ -378,7 +378,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
                 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 {
index 9c4945d74dbfef9e82e07bffd3d04441f413d151..b6f9ae36da70c4af2c3f58feae08740958237a40 100644 (file)
@@ -2216,7 +2216,7 @@ pub fn span_with_attributes(&self) -> Span {
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
 pub struct FnHeader {
     pub unsafety: Unsafety,
-    pub asyncness: IsAsync,
+    pub asyncness: Spanned<IsAsync>,
     pub constness: Spanned<Constness>,
     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,
         }
index 27b0cfb163077e8d2ba28731a415d9690169f20d..2f88749ace85ea3048ac6b4698c0fef69fd0270c 100644 (file)
@@ -1017,7 +1017,7 @@ fn item_fn_poly(&self,
                   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,
                               },
index d574b410ccc0625834afb09d3a62929edcdd6107..0f7ba041f9c0836b9b882a97c895295bdee4de58 100644 (file)
@@ -1894,7 +1894,7 @@ fn visit_fn(&mut self,
         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
index 86849f580d081eda2fe59f9ce53c8769bf92070d..935142e8a2def2a65440c5401218349a73d58029 100644 (file)
@@ -926,7 +926,7 @@ pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut
 
 pub fn noop_visit_fn_header<T: MutVisitor>(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<T: MutVisitor>(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) {
index 5a753e1f8c8a5d932c6d7c09513bba9d0be5cd2b..c257f05ae468eecee2587a25701b61cb4f800410 100644 (file)
@@ -5001,6 +5001,11 @@ fn is_async_block(&mut self) -> bool {
         )
     }
 
+    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 @@ fn parse_stmt_without_recovery(&mut self,
                   !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 @@ fn mk_item(&mut self, span: Span, ident: Ident, node: ItemKind, vis: Visibility,
     /// Parses an item-position function declaration.
     fn parse_item_fn(&mut self,
                      unsafety: Unsafety,
-                     asyncness: IsAsync,
+                     asyncness: Spanned<IsAsync>,
                      constness: Spanned<Constness>,
                      abi: Abi)
                      -> PResult<'a, ItemInfo> {
@@ -6378,7 +6384,7 @@ fn parse_fn_front_matter(&mut self)
         -> PResult<'a, (
             Spanned<Constness>,
             Unsafety,
-            IsAsync,
+            Spanned<IsAsync>,
             Abi
         )>
     {
@@ -6386,6 +6392,7 @@ fn parse_fn_front_matter(&mut self)
         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 @@ fn parse_item_implementation(
                 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 @@ fn parse_item_implementation(
                 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 @@ fn parse_item_implementation(
             // 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 @@ fn parse_item_implementation(
                                     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 @@ fn parse_item_implementation(
             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 @@ fn parse_item_implementation(
             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 @@ fn parse_macro_use_or_failure(
         lo: Span,
         visibility: Visibility
     ) -> PResult<'a, Option<P<Item>>> {
-        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 @@ fn parse_macro_use_or_failure(
     fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
                                at_end: &mut bool) -> PResult<'a, Option<Mac>>
     {
-        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)?;
index dcf9815f6d1ba47a4df2facd444514455fb87293..d6265ebde1bbc9dcb1d97dd8748d7a372ee7c872 100644 (file)
@@ -3195,7 +3195,7 @@ pub fn print_fn_header_info(&mut self,
             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 @@ fn test_fun_to_string() {
                     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,
index a002394c710fe064611c6ccc6ac9f4165377c971..46d8d772e9321ac707c7b6eba245a66de378cf84 100644 (file)
@@ -22,7 +22,7 @@
 #[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 @@ fn visit_vis(&mut self, vis: &'ast Visibility) {
     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)) => {
index 371862465487b3f2cb5d7e13c53fe06f122d1341..f4b625f8ea2c862c69bec862608d001c7f377fe8 100644 (file)
@@ -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 (file)
index 0000000..2105aa5
--- /dev/null
@@ -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 (file)
index 0000000..1ad907a
--- /dev/null
@@ -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`.
index 84dd1b9f814c2c60b7333988746e421083161fe9..b6ab8ae0a9bc7c6b4a27f080194d07dc8e674bf6 100644 (file)
@@ -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`
index 450b2c42f119d9f431fb824836b5a5f69d3e4783..58051153e1f0df72c43f74f9a6f5e4b09a54eb56 100644 (file)
@@ -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 (file)
index 0000000..4064252
--- /dev/null
@@ -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 (file)
index 0000000..acdeabb
--- /dev/null
@@ -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`.
index facb191a37081f64e33add598c99d11cf0e1029b..869876dc6a88a3e6c7f53a5cb129a3044227125f 100644 (file)
@@ -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()
 }
index 8a8789120577e72a681b3d57d7bf3a0e18b1d858..96494229fd339f6d70e97d85d19ba63146b35e21 100644 (file)
@@ -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`.