summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-02-27 13:32:21 +0100
committerGitHub <noreply@github.com>2019-02-27 13:32:21 +0100
commitf84a8cf28a5e914ae13f4d8d9c15468268e415d4 (patch)
treefbf44e7b47ed63bee29136fe78e24d2c643d2c56
parenta46b00eeb5cb78288f04df0ab68b4192c92608c9 (diff)
parent8300f51936149ec43eb063205e4d03c54a308f3c (diff)
downloadrust-f84a8cf28a5e914ae13f4d8d9c15468268e415d4.tar.gz
Rollup merge of #58678 - doctorn:refuse-async-fn-2015-edition, r=varkor
Deny `async fn` in 2015 edition This commit prevents code using `async fn` from being compiled in Rust 2015 edition. Compiling code of the form: ```rust async fn foo() {} ``` Will now result in the error: ``` error[E0670]: `async fn` is not permitted in the 2015 edition --> async.rs:1:1 | 1 | async fn foo() {} | ^^^^^ error: aborting due to error For more information about an error, try `rustc --explain E0670`. ``` This resolves #58652 and also resolves #53714. r? @varkor
-rw-r--r--src/librustc/hir/lowering.rs10
-rw-r--r--src/librustc/hir/map/def_collector.rs10
-rw-r--r--src/librustc_passes/ast_validation.rs14
-rw-r--r--src/librustc_passes/diagnostics.rs12
-rw-r--r--src/librustc_resolve/lib.rs4
-rw-r--r--src/librustc_save_analysis/sig.rs4
-rw-r--r--src/libsyntax/ast.rs4
-rw-r--r--src/libsyntax/ext/build.rs2
-rw-r--r--src/libsyntax/feature_gate.rs2
-rw-r--r--src/libsyntax/mut_visit.rs2
-rw-r--r--src/libsyntax/parse/parser.rs39
-rw-r--r--src/libsyntax/print/pprust.rs4
-rw-r--r--src/libsyntax/visit.rs15
-rw-r--r--src/libsyntax_ext/test.rs2
-rw-r--r--src/test/ui/editions/edition-deny-async-fns-2015.rs34
-rw-r--r--src/test/ui/editions/edition-deny-async-fns-2015.stderr58
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs3
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr16
-rw-r--r--src/test/ui/impl-trait/recursive-async-impl-trait-type.rs11
-rw-r--r--src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr11
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type.rs6
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type.stderr14
22 files changed, 215 insertions, 62 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 0211dd72875..df45a085944 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2892,7 +2892,7 @@ impl<'a> LoweringContext<'a> {
// `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,
@@ -2902,7 +2902,7 @@ impl<'a> LoweringContext<'a> {
decl,
Some((fn_def_id, idty)),
true,
- header.asyncness.opt_return_id()
+ header.asyncness.node.opt_return_id()
),
);
@@ -3398,14 +3398,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))
}
@@ -3624,7 +3624,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 72aa9570cc2..12760f8b982 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 606ae274128..f96fc3b897f 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 19d4d3aeb0f..e3c6b16703a 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 ac572b65213..e9331fcd8ba 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 50a335bf908..52f3a207770 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 9c4945d74db..b6f9ae36da7 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<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,
}
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 27b0cfb1630..2f88749ace8 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 cc1953e69d4..8df1f38d60d 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1898,7 +1898,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 bcb96f5786b..d30372d45d7 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -934,7 +934,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) {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 7e900dfeb1e..b762365c31f 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) {
@@ -6384,7 +6390,7 @@ impl<'a> Parser<'a> {
/// 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> {
@@ -6416,7 +6422,7 @@ impl<'a> Parser<'a> {
-> PResult<'a, (
Spanned<Constness>,
Unsafety,
- IsAsync,
+ Spanned<IsAsync>,
Abi
)>
{
@@ -6424,6 +6430,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 {
@@ -7834,7 +7841,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;
@@ -7878,7 +7885,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;
@@ -7926,14 +7933,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;
@@ -7942,6 +7950,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) &&
@@ -7989,7 +8004,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;
@@ -8015,7 +8030,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;
@@ -8282,7 +8297,8 @@ impl<'a> Parser<'a> {
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;
@@ -8337,7 +8353,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<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)?;
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index dcf9815f6d1..d6265ebde1b 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 a002394c710..46d8d772e93 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 37186246548..f4b625f8ea2 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 00000000000..2105aa5835d
--- /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 00000000000..1ad907aa7eb
--- /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 84dd1b9f814..b6ab8ae0a9b 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 450b2c42f11..58051153e1f 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 00000000000..40642523be2
--- /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 00000000000..acdeabb2f98
--- /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 facb191a370..869876dc6a8 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 8a878912057..96494229fd3 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`.