Skip to content

Commit 9c44efd

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#58652 and also resolves rust-lang#53714. r? @varkor
2 parents 34baa82 + 8300f51 commit 9c44efd

22 files changed

+215
-62
lines changed

src/librustc/hir/lowering.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -2892,7 +2892,7 @@ impl<'a> LoweringContext<'a> {
28922892
// `impl Future<Output = T>` here because lower_body
28932893
// only cares about the input argument patterns in the function
28942894
// declaration (decl), not the return types.
2895-
let body_id = this.lower_async_body(decl, header.asyncness, body);
2895+
let body_id = this.lower_async_body(decl, header.asyncness.node, body);
28962896

28972897
let (generics, fn_decl) = this.add_in_band_defs(
28982898
generics,
@@ -2902,7 +2902,7 @@ impl<'a> LoweringContext<'a> {
29022902
decl,
29032903
Some((fn_def_id, idty)),
29042904
true,
2905-
header.asyncness.opt_return_id()
2905+
header.asyncness.node.opt_return_id()
29062906
),
29072907
);
29082908

@@ -3398,14 +3398,14 @@ impl<'a> LoweringContext<'a> {
33983398
)
33993399
}
34003400
ImplItemKind::Method(ref sig, ref body) => {
3401-
let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness, body);
3401+
let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body);
34023402
let impl_trait_return_allow = !self.is_in_trait_impl;
34033403
let (generics, sig) = self.lower_method_sig(
34043404
&i.generics,
34053405
sig,
34063406
impl_item_def_id,
34073407
impl_trait_return_allow,
3408-
sig.header.asyncness.opt_return_id(),
3408+
sig.header.asyncness.node.opt_return_id(),
34093409
);
34103410
(generics, hir::ImplItemKind::Method(sig, body_id))
34113411
}
@@ -3624,7 +3624,7 @@ impl<'a> LoweringContext<'a> {
36243624
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
36253625
hir::FnHeader {
36263626
unsafety: self.lower_unsafety(h.unsafety),
3627-
asyncness: self.lower_asyncness(h.asyncness),
3627+
asyncness: self.lower_asyncness(h.asyncness.node),
36283628
constness: self.lower_constness(h.constness),
36293629
abi: h.abi,
36303630
}

src/librustc/hir/map/def_collector.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl<'a> DefCollector<'a> {
7373
decl: &'a FnDecl,
7474
body: &'a Block,
7575
) {
76-
let (closure_id, return_impl_trait_id) = match header.asyncness {
76+
let (closure_id, return_impl_trait_id) = match header.asyncness.node {
7777
IsAsync::Async {
7878
closure_id,
7979
return_impl_trait_id,
@@ -129,10 +129,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
129129
}
130130
ItemKind::Fn(
131131
ref decl,
132-
ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
132+
ref header,
133133
ref generics,
134134
ref body,
135-
) => {
135+
) if header.asyncness.node.is_async() => {
136136
return self.visit_async_fn(
137137
i.id,
138138
i.ident.name,
@@ -242,9 +242,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
242242
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
243243
let def_data = match ii.node {
244244
ImplItemKind::Method(MethodSig {
245-
header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
245+
ref header,
246246
ref decl,
247-
}, ref body) => {
247+
}, ref body) if header.asyncness.node.is_async() => {
248248
return self.visit_async_fn(
249249
ii.id,
250250
ii.ident.name,

src/librustc_passes/ast_validation.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
463463
self.invalid_visibility(&impl_item.vis, None);
464464
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
465465
self.check_trait_fn_not_const(sig.header.constness);
466-
self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness);
466+
self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
467467
}
468468
}
469469
}
@@ -482,9 +482,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
482482
.note("only trait implementations may be annotated with default").emit();
483483
}
484484
}
485-
ItemKind::Fn(_, header, ref generics, _) => {
485+
ItemKind::Fn(_, ref header, ref generics, _) => {
486486
// We currently do not permit const generics in `const fn`, as
487487
// this is tantamount to allowing compile-time dependent typing.
488+
self.visit_fn_header(header);
488489
if header.constness.node == Constness::Const {
489490
// Look for const generics and error if we find any.
490491
for param in &generics.params {
@@ -535,7 +536,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
535536
self.no_questions_in_bounds(bounds, "supertraits", true);
536537
for trait_item in trait_items {
537538
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
538-
self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness);
539+
self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
539540
self.check_trait_fn_not_const(sig.header.constness);
540541
if block.is_none() {
541542
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
@@ -702,6 +703,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
702703
.span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \
703704
the relevant `fold_*()` method in `PlaceholderExpander`?");
704705
}
706+
707+
fn visit_fn_header(&mut self, header: &'a FnHeader) {
708+
if header.asyncness.node.is_async() && self.session.rust_2015() {
709+
struct_span_err!(self.session, header.asyncness.span, E0670,
710+
"`async fn` is not permitted in the 2015 edition").emit();
711+
}
712+
}
705713
}
706714

707715
pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) {

src/librustc_passes/diagnostics.rs

+12
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,18 @@ loop {
310310
break;
311311
}
312312
```
313+
"##,
314+
315+
E0670: r##"
316+
Rust 2015 does not permit the use of `async fn`.
317+
318+
Example of erroneous code:
319+
320+
```compile_fail,E0670
321+
async fn foo() {}
322+
```
323+
324+
Switch to the Rust 2018 edition to use `async fn`.
313325
"##
314326
}
315327

src/librustc_resolve/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -806,9 +806,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
806806
debug!("(resolving function) entering function");
807807
let (rib_kind, asyncness) = match function_kind {
808808
FnKind::ItemFn(_, ref header, ..) =>
809-
(ItemRibKind, header.asyncness),
809+
(ItemRibKind, header.asyncness.node),
810810
FnKind::Method(_, ref sig, _, _) =>
811-
(TraitOrImplItemRibKind, sig.header.asyncness),
811+
(TraitOrImplItemRibKind, sig.header.asyncness.node),
812812
FnKind::Closure(_) =>
813813
// Async closures aren't resolved through `visit_fn`-- they're
814814
// processed separately

src/librustc_save_analysis/sig.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ impl Sig for ast::Item {
378378
if header.constness.node == ast::Constness::Const {
379379
text.push_str("const ");
380380
}
381-
if header.asyncness.is_async() {
381+
if header.asyncness.node.is_async() {
382382
text.push_str("async ");
383383
}
384384
if header.unsafety == ast::Unsafety::Unsafe {
@@ -936,7 +936,7 @@ fn make_method_signature(
936936
if m.header.constness.node == ast::Constness::Const {
937937
text.push_str("const ");
938938
}
939-
if m.header.asyncness.is_async() {
939+
if m.header.asyncness.node.is_async() {
940940
text.push_str("async ");
941941
}
942942
if m.header.unsafety == ast::Unsafety::Unsafe {

src/libsyntax/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2216,7 +2216,7 @@ impl Item {
22162216
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
22172217
pub struct FnHeader {
22182218
pub unsafety: Unsafety,
2219-
pub asyncness: IsAsync,
2219+
pub asyncness: Spanned<IsAsync>,
22202220
pub constness: Spanned<Constness>,
22212221
pub abi: Abi,
22222222
}
@@ -2225,7 +2225,7 @@ impl Default for FnHeader {
22252225
fn default() -> FnHeader {
22262226
FnHeader {
22272227
unsafety: Unsafety::Normal,
2228-
asyncness: IsAsync::NotAsync,
2228+
asyncness: dummy_spanned(IsAsync::NotAsync),
22292229
constness: dummy_spanned(Constness::NotConst),
22302230
abi: Abi::Rust,
22312231
}

src/libsyntax/ext/build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
10171017
ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)),
10181018
ast::FnHeader {
10191019
unsafety: ast::Unsafety::Normal,
1020-
asyncness: ast::IsAsync::NotAsync,
1020+
asyncness: dummy_spanned(ast::IsAsync::NotAsync),
10211021
constness: dummy_spanned(ast::Constness::NotConst),
10221022
abi: Abi::Rust,
10231023
},

src/libsyntax/feature_gate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1898,7 +1898,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
18981898
match fn_kind {
18991899
FnKind::ItemFn(_, header, _, _) => {
19001900
// Check for const fn and async fn declarations.
1901-
if header.asyncness.is_async() {
1901+
if header.asyncness.node.is_async() {
19021902
gate_feature_post!(&self, async_await, span, "async fn is unstable");
19031903
}
19041904
// Stability of const fn methods are covered in

src/libsyntax/mut_visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@ pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut
934934

935935
pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
936936
let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header;
937-
vis.visit_asyncness(asyncness);
937+
vis.visit_asyncness(&mut asyncness.node);
938938
}
939939

940940
pub fn noop_visit_mod<T: MutVisitor>(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) {

src/libsyntax/parse/parser.rs

+28-11
Original file line numberDiff line numberDiff line change
@@ -5001,6 +5001,11 @@ impl<'a> Parser<'a> {
50015001
)
50025002
}
50035003

5004+
fn is_async_fn(&mut self) -> bool {
5005+
self.token.is_keyword(keywords::Async) &&
5006+
self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
5007+
}
5008+
50045009
fn is_do_catch_block(&mut self) -> bool {
50055010
self.token.is_keyword(keywords::Do) &&
50065011
self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
@@ -5133,7 +5138,8 @@ impl<'a> Parser<'a> {
51335138
!self.is_union_item() &&
51345139
!self.is_crate_vis() &&
51355140
!self.is_existential_type_decl() &&
5136-
!self.is_auto_trait_item() {
5141+
!self.is_auto_trait_item() &&
5142+
!self.is_async_fn() {
51375143
let pth = self.parse_path(PathStyle::Expr)?;
51385144

51395145
if !self.eat(&token::Not) {
@@ -6384,7 +6390,7 @@ impl<'a> Parser<'a> {
63846390
/// Parses an item-position function declaration.
63856391
fn parse_item_fn(&mut self,
63866392
unsafety: Unsafety,
6387-
asyncness: IsAsync,
6393+
asyncness: Spanned<IsAsync>,
63886394
constness: Spanned<Constness>,
63896395
abi: Abi)
63906396
-> PResult<'a, ItemInfo> {
@@ -6416,14 +6422,15 @@ impl<'a> Parser<'a> {
64166422
-> PResult<'a, (
64176423
Spanned<Constness>,
64186424
Unsafety,
6419-
IsAsync,
6425+
Spanned<IsAsync>,
64206426
Abi
64216427
)>
64226428
{
64236429
let is_const_fn = self.eat_keyword(keywords::Const);
64246430
let const_span = self.prev_span;
64256431
let unsafety = self.parse_unsafety();
64266432
let asyncness = self.parse_asyncness();
6433+
let asyncness = respan(self.prev_span, asyncness);
64276434
let (constness, unsafety, abi) = if is_const_fn {
64286435
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
64296436
} else {
@@ -7834,7 +7841,7 @@ impl<'a> Parser<'a> {
78347841
let abi = opt_abi.unwrap_or(Abi::C);
78357842
let (ident, item_, extra_attrs) =
78367843
self.parse_item_fn(Unsafety::Normal,
7837-
IsAsync::NotAsync,
7844+
respan(fn_span, IsAsync::NotAsync),
78387845
respan(fn_span, Constness::NotConst),
78397846
abi)?;
78407847
let prev_span = self.prev_span;
@@ -7878,7 +7885,7 @@ impl<'a> Parser<'a> {
78787885
self.bump();
78797886
let (ident, item_, extra_attrs) =
78807887
self.parse_item_fn(unsafety,
7881-
IsAsync::NotAsync,
7888+
respan(const_span, IsAsync::NotAsync),
78827889
respan(const_span, Constness::Const),
78837890
Abi::Rust)?;
78847891
let prev_span = self.prev_span;
@@ -7926,14 +7933,15 @@ impl<'a> Parser<'a> {
79267933
// ASYNC FUNCTION ITEM
79277934
let unsafety = self.parse_unsafety();
79287935
self.expect_keyword(keywords::Async)?;
7936+
let async_span = self.prev_span;
79297937
self.expect_keyword(keywords::Fn)?;
79307938
let fn_span = self.prev_span;
79317939
let (ident, item_, extra_attrs) =
79327940
self.parse_item_fn(unsafety,
7933-
IsAsync::Async {
7941+
respan(async_span, IsAsync::Async {
79347942
closure_id: ast::DUMMY_NODE_ID,
79357943
return_impl_trait_id: ast::DUMMY_NODE_ID,
7936-
},
7944+
}),
79377945
respan(fn_span, Constness::NotConst),
79387946
Abi::Rust)?;
79397947
let prev_span = self.prev_span;
@@ -7942,6 +7950,13 @@ impl<'a> Parser<'a> {
79427950
item_,
79437951
visibility,
79447952
maybe_append(attrs, extra_attrs));
7953+
if self.span.rust_2015() {
7954+
self.diagnostic().struct_span_err_with_code(
7955+
async_span,
7956+
"`async fn` is not permitted in the 2015 edition",
7957+
DiagnosticId::Error("E0670".into())
7958+
).emit();
7959+
}
79457960
return Ok(Some(item));
79467961
}
79477962
if self.check_keyword(keywords::Unsafe) &&
@@ -7989,7 +8004,7 @@ impl<'a> Parser<'a> {
79898004
let fn_span = self.prev_span;
79908005
let (ident, item_, extra_attrs) =
79918006
self.parse_item_fn(Unsafety::Normal,
7992-
IsAsync::NotAsync,
8007+
respan(fn_span, IsAsync::NotAsync),
79938008
respan(fn_span, Constness::NotConst),
79948009
Abi::Rust)?;
79958010
let prev_span = self.prev_span;
@@ -8015,7 +8030,7 @@ impl<'a> Parser<'a> {
80158030
let fn_span = self.prev_span;
80168031
let (ident, item_, extra_attrs) =
80178032
self.parse_item_fn(Unsafety::Unsafe,
8018-
IsAsync::NotAsync,
8033+
respan(fn_span, IsAsync::NotAsync),
80198034
respan(fn_span, Constness::NotConst),
80208035
abi)?;
80218036
let prev_span = self.prev_span;
@@ -8282,7 +8297,8 @@ impl<'a> Parser<'a> {
82828297
lo: Span,
82838298
visibility: Visibility
82848299
) -> PResult<'a, Option<P<Item>>> {
8285-
if macros_allowed && self.token.is_path_start() {
8300+
if macros_allowed && self.token.is_path_start() &&
8301+
!(self.is_async_fn() && self.span.rust_2015()) {
82868302
// MACRO INVOCATION ITEM
82878303

82888304
let prev_span = self.prev_span;
@@ -8337,7 +8353,8 @@ impl<'a> Parser<'a> {
83378353
fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
83388354
at_end: &mut bool) -> PResult<'a, Option<Mac>>
83398355
{
8340-
if self.token.is_path_start() {
8356+
if self.token.is_path_start() &&
8357+
!(self.is_async_fn() && self.span.rust_2015()) {
83418358
let prev_span = self.prev_span;
83428359
let lo = self.span;
83438360
let pth = self.parse_path(PathStyle::Mod)?;

src/libsyntax/print/pprust.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3195,7 +3195,7 @@ impl<'a> State<'a> {
31953195
ast::Constness::Const => self.word_nbsp("const")?
31963196
}
31973197

3198-
self.print_asyncness(header.asyncness)?;
3198+
self.print_asyncness(header.asyncness.node)?;
31993199
self.print_unsafety(header.unsafety)?;
32003200

32013201
if header.abi != Abi::Rust {
@@ -3247,7 +3247,7 @@ mod tests {
32473247
ast::FnHeader {
32483248
unsafety: ast::Unsafety::Normal,
32493249
constness: source_map::dummy_spanned(ast::Constness::NotConst),
3250-
asyncness: ast::IsAsync::NotAsync,
3250+
asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync),
32513251
abi: Abi::Rust,
32523252
},
32533253
abba_ident,

0 commit comments

Comments
 (0)