Skip to content

Commit ce1d95a

Browse files
committed
Always parse 'async unsafe fn' + properly ban in 2015.
1 parent 9a90d03 commit ce1d95a

File tree

7 files changed

+77
-28
lines changed

7 files changed

+77
-28
lines changed

src/librustc_passes/ast_validation.rs

-7
Original file line numberDiff line numberDiff line change
@@ -837,13 +837,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
837837
the relevant `fold_*()` method in `PlaceholderExpander`?");
838838
}
839839

840-
fn visit_fn_header(&mut self, header: &'a FnHeader) {
841-
if header.asyncness.node.is_async() && self.session.rust_2015() {
842-
struct_span_err!(self.session, header.asyncness.span, E0670,
843-
"`async fn` is not permitted in the 2015 edition").emit();
844-
}
845-
}
846-
847840
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
848841
match ii.node {
849842
ImplItemKind::Method(ref sig, _) => {

src/libsyntax/parse/parser.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -5734,9 +5734,12 @@ impl<'a> Parser<'a> {
57345734
{
57355735
let is_const_fn = self.eat_keyword(kw::Const);
57365736
let const_span = self.prev_span;
5737-
let unsafety = self.parse_unsafety();
57385737
let asyncness = self.parse_asyncness();
5738+
if let IsAsync::Async { .. } = asyncness {
5739+
self.ban_async_in_2015(self.prev_span);
5740+
}
57395741
let asyncness = respan(self.prev_span, asyncness);
5742+
let unsafety = self.parse_unsafety();
57405743
let (constness, unsafety, abi) = if is_const_fn {
57415744
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
57425745
} else {
@@ -7254,13 +7257,7 @@ impl<'a> Parser<'a> {
72547257
item_,
72557258
visibility,
72567259
maybe_append(attrs, extra_attrs));
7257-
if self.token.span.rust_2015() {
7258-
self.diagnostic().struct_span_err_with_code(
7259-
async_span,
7260-
"`async fn` is not permitted in the 2015 edition",
7261-
DiagnosticId::Error("E0670".into())
7262-
).emit();
7263-
}
7260+
self.ban_async_in_2015(async_span);
72647261
return Ok(Some(item));
72657262
}
72667263
}
@@ -7534,6 +7531,19 @@ impl<'a> Parser<'a> {
75347531
self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility)
75357532
}
75367533

7534+
/// We are parsing `async fn`. If we are on Rust 2015, emit an error.
7535+
fn ban_async_in_2015(&self, async_span: Span) {
7536+
if async_span.rust_2015() {
7537+
self.diagnostic()
7538+
.struct_span_err_with_code(
7539+
async_span,
7540+
"`async fn` is not permitted in the 2015 edition",
7541+
DiagnosticId::Error("E0670".into())
7542+
)
7543+
.emit();
7544+
}
7545+
}
7546+
75377547
/// Parses a foreign item.
75387548
crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> {
75397549
maybe_whole!(self, NtForeignItem, |ni| ni);

src/test/ui/async-await/async-await.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,15 @@ trait Bar {
134134
}
135135

136136
impl Foo {
137-
async fn async_method(x: u8) -> u8 {
137+
async fn async_assoc_item(x: u8) -> u8 {
138138
unsafe {
139139
unsafe_async_fn(x).await
140140
}
141141
}
142+
143+
async unsafe fn async_unsafe_assoc_item(x: u8) -> u8 {
144+
unsafe_async_fn(x).await
145+
}
142146
}
143147

144148
fn test_future_yields_once_then_returns<F, Fut>(f: F)
@@ -180,12 +184,17 @@ fn main() {
180184
async_fn,
181185
generic_async_fn,
182186
async_fn_with_internal_borrow,
183-
Foo::async_method,
187+
Foo::async_assoc_item,
184188
|x| {
185189
async move {
186190
unsafe { unsafe_async_fn(x).await }
187191
}
188192
},
193+
|x| {
194+
async move {
195+
unsafe { Foo::async_unsafe_assoc_item(x).await }
196+
}
197+
},
189198
}
190199
test_with_borrow! {
191200
async_block_with_borrow_named_lifetime,

src/test/ui/async-await/edition-deny-async-fns-2015.rs

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ fn main() {
2828
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
2929
}
3030

31+
accept_item! {
32+
impl Foo {
33+
async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
34+
}
35+
}
36+
3137
let inside_closure = || {
3238
async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
3339
};

src/test/ui/async-await/edition-deny-async-fns-2015.stderr

+17-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,19 @@ LL | async fn async_baz() {
2323
| ^^^^^
2424

2525
error[E0670]: `async fn` is not permitted in the 2015 edition
26-
--> $DIR/edition-deny-async-fns-2015.rs:32:9
26+
--> $DIR/edition-deny-async-fns-2015.rs:16:5
27+
|
28+
LL | async fn foo() {}
29+
| ^^^^^
30+
31+
error[E0670]: `async fn` is not permitted in the 2015 edition
32+
--> $DIR/edition-deny-async-fns-2015.rs:20:5
33+
|
34+
LL | async fn foo() {}
35+
| ^^^^^
36+
37+
error[E0670]: `async fn` is not permitted in the 2015 edition
38+
--> $DIR/edition-deny-async-fns-2015.rs:38:9
2739
|
2840
LL | async fn bar() {}
2941
| ^^^^^
@@ -35,23 +47,17 @@ LL | async fn foo() {}
3547
| ^^^^^
3648

3749
error[E0670]: `async fn` is not permitted in the 2015 edition
38-
--> $DIR/edition-deny-async-fns-2015.rs:16:5
50+
--> $DIR/edition-deny-async-fns-2015.rs:33:13
3951
|
40-
LL | async fn foo() {}
41-
| ^^^^^
52+
LL | async fn bar() {}
53+
| ^^^^^
4254

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

49-
error[E0670]: `async fn` is not permitted in the 2015 edition
50-
--> $DIR/edition-deny-async-fns-2015.rs:20:5
51-
|
52-
LL | async fn foo() {}
53-
| ^^^^^
54-
55-
error: aborting due to 9 previous errors
61+
error: aborting due to 10 previous errors
5662

5763
For more information about this error, try `rustc --explain E0670`.
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// edition:2018
2+
3+
struct S;
4+
5+
impl S {
6+
#[cfg(FALSE)]
7+
unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found `async`
8+
}
9+
10+
#[cfg(FALSE)]
11+
unsafe async fn f() {} //~ ERROR expected one of `extern`, `fn`, or `{`, found `async`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: expected one of `extern` or `fn`, found `async`
2+
--> $DIR/no-unsafe-async.rs:7:12
3+
|
4+
LL | unsafe async fn g() {}
5+
| ^^^^^ expected one of `extern` or `fn` here
6+
7+
error: expected one of `extern`, `fn`, or `{`, found `async`
8+
--> $DIR/no-unsafe-async.rs:11:8
9+
|
10+
LL | unsafe async fn f() {}
11+
| ^^^^^ expected one of `extern`, `fn`, or `{` here
12+
13+
error: aborting due to 2 previous errors
14+

0 commit comments

Comments
 (0)