Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always parse 'async unsafe fn' + properly ban in 2015 #62241

Merged
merged 1 commit into from
Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions src/librustc_passes/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,13 +837,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
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();
}
}

fn visit_impl_item(&mut self, ii: &'a ImplItem) {
match ii.node {
ImplItemKind::Method(ref sig, _) => {
Expand Down
26 changes: 18 additions & 8 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5734,9 +5734,12 @@ impl<'a> Parser<'a> {
{
let is_const_fn = self.eat_keyword(kw::Const);
let const_span = self.prev_span;
let unsafety = self.parse_unsafety();
let asyncness = self.parse_asyncness();
if let IsAsync::Async { .. } = asyncness {
self.ban_async_in_2015(self.prev_span);
}
let asyncness = respan(self.prev_span, asyncness);
let unsafety = self.parse_unsafety();
let (constness, unsafety, abi) = if is_const_fn {
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
} else {
Expand Down Expand Up @@ -7254,13 +7257,7 @@ impl<'a> Parser<'a> {
item_,
visibility,
maybe_append(attrs, extra_attrs));
if self.token.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();
}
self.ban_async_in_2015(async_span);
return Ok(Some(item));
}
}
Expand Down Expand Up @@ -7534,6 +7531,19 @@ impl<'a> Parser<'a> {
self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility)
}

/// We are parsing `async fn`. If we are on Rust 2015, emit an error.
fn ban_async_in_2015(&self, async_span: Span) {
if async_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();
}
}

/// Parses a foreign item.
crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> {
maybe_whole!(self, NtForeignItem, |ni| ni);
Expand Down
13 changes: 11 additions & 2 deletions src/test/ui/async-await/async-await.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,15 @@ trait Bar {
}

impl Foo {
async fn async_method(x: u8) -> u8 {
async fn async_assoc_item(x: u8) -> u8 {
unsafe {
unsafe_async_fn(x).await
}
}

async unsafe fn async_unsafe_assoc_item(x: u8) -> u8 {
unsafe_async_fn(x).await
}
}

fn test_future_yields_once_then_returns<F, Fut>(f: F)
Expand Down Expand Up @@ -180,12 +184,17 @@ fn main() {
async_fn,
generic_async_fn,
async_fn_with_internal_borrow,
Foo::async_method,
Foo::async_assoc_item,
|x| {
async move {
unsafe { unsafe_async_fn(x).await }
}
},
|x| {
async move {
unsafe { Foo::async_unsafe_assoc_item(x).await }
}
},
}
test_with_borrow! {
async_block_with_borrow_named_lifetime,
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/async-await/edition-deny-async-fns-2015.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ fn main() {
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
}

accept_item! {
impl Foo {
async fn bar() {} //~ 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
};
Expand Down
28 changes: 17 additions & 11 deletions src/test/ui/async-await/edition-deny-async-fns-2015.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,19 @@ LL | async fn async_baz() {
| ^^^^^

error[E0670]: `async fn` is not permitted in the 2015 edition
--> $DIR/edition-deny-async-fns-2015.rs:32:9
--> $DIR/edition-deny-async-fns-2015.rs:16:5
|
LL | async fn foo() {}
| ^^^^^

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[E0670]: `async fn` is not permitted in the 2015 edition
--> $DIR/edition-deny-async-fns-2015.rs:38:9
|
LL | async fn bar() {}
| ^^^^^
Expand All @@ -35,23 +47,17 @@ LL | async fn foo() {}
| ^^^^^

error[E0670]: `async fn` is not permitted in the 2015 edition
--> $DIR/edition-deny-async-fns-2015.rs:16:5
--> $DIR/edition-deny-async-fns-2015.rs:33:13
|
LL | async fn foo() {}
| ^^^^^
LL | async fn bar() {}
| ^^^^^

error[E0706]: trait fns cannot be declared `async`
--> $DIR/edition-deny-async-fns-2015.rs:20:5
|
LL | async fn foo() {}
| ^^^^^^^^^^^^^^^^^

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: aborting due to 9 previous errors
error: aborting due to 10 previous errors

For more information about this error, try `rustc --explain E0670`.
11 changes: 11 additions & 0 deletions src/test/ui/async-await/no-unsafe-async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// edition:2018

struct S;

impl S {
#[cfg(FALSE)]
unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found `async`
}

#[cfg(FALSE)]
unsafe async fn f() {} //~ ERROR expected one of `extern`, `fn`, or `{`, found `async`
14 changes: 14 additions & 0 deletions src/test/ui/async-await/no-unsafe-async.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: expected one of `extern` or `fn`, found `async`
--> $DIR/no-unsafe-async.rs:7:12
|
LL | unsafe async fn g() {}
| ^^^^^ expected one of `extern` or `fn` here

error: expected one of `extern`, `fn`, or `{`, found `async`
--> $DIR/no-unsafe-async.rs:11:8
|
LL | unsafe async fn f() {}
| ^^^^^ expected one of `extern`, `fn`, or `{` here

error: aborting due to 2 previous errors