diff options
| author | bors <bors@rust-lang.org> | 2023-12-10 08:08:03 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-12-10 08:08:03 +0000 |
| commit | 92ab9d65bb8f3a1b167c2ccb9d22de301a7aef45 (patch) | |
| tree | 0a9542f67746bf7a90b8bb4881b56de39b138cb9 /compiler/rustc_parse/src/parser | |
| parent | aa7afff8c619fc9c04515b7cef57d72dc3c7e51e (diff) | |
| parent | 035d86594ddcaec12b59c35f8de1a99c3b8b81fb (diff) | |
| download | rust-92ab9d65bb8f3a1b167c2ccb9d22de301a7aef45.tar.gz rust-92ab9d65bb8f3a1b167c2ccb9d22de301a7aef45.zip | |
Auto merge of #3217 - RalfJung:rustup, r=RalfJung
Rustup Pulls in https://github.com/rust-lang/rust/pull/117953 (in preparation for implementing those intrinsics)
Diffstat (limited to 'compiler/rustc_parse/src/parser')
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 297 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 55 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 39 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 4 |
6 files changed, 240 insertions, 204 deletions
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 7ab0d3f35ea..5295172b25e 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2839,7 +2839,6 @@ impl<'a> Parser<'a> { pub(crate) fn maybe_recover_unexpected_comma( &mut self, lo: Span, - is_mac_invoc: bool, rt: CommaRecoveryMode, ) -> PResult<'a, ()> { if self.token != token::Comma { @@ -2860,28 +2859,24 @@ impl<'a> Parser<'a> { let seq_span = lo.to(self.prev_token.span); let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { - if is_mac_invoc { - err.note(fluent::parse_macro_expands_to_match_arm); - } else { - err.multipart_suggestion( - format!( - "try adding parentheses to match on a tuple{}", - if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." }, - ), - vec![ - (seq_span.shrink_to_lo(), "(".to_string()), - (seq_span.shrink_to_hi(), ")".to_string()), - ], + err.multipart_suggestion( + format!( + "try adding parentheses to match on a tuple{}", + if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." }, + ), + vec![ + (seq_span.shrink_to_lo(), "(".to_string()), + (seq_span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MachineApplicable, + ); + if let CommaRecoveryMode::EitherTupleOrPipe = rt { + err.span_suggestion( + seq_span, + "...or a vertical bar to match on multiple alternatives", + seq_snippet.replace(',', " |"), Applicability::MachineApplicable, ); - if let CommaRecoveryMode::EitherTupleOrPipe = rt { - err.span_suggestion( - seq_span, - "...or a vertical bar to match on multiple alternatives", - seq_snippet.replace(',', " |"), - Applicability::MachineApplicable, - ); - } } } Err(err) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8482824ec4b..406a6def019 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1442,20 +1442,21 @@ impl<'a> Parser<'a> { } else if this.token.uninterpolated_span().at_least_rust_2018() { // `Span:.at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. if this.check_keyword(kw::Async) { - if this.is_gen_block(kw::Async) { - // Check for `async {` and `async move {`. + // FIXME(gen_blocks): Parse `gen async` and suggest swap + if this.is_gen_block(kw::Async, 0) { + // Check for `async {` and `async move {`, + // or `async gen {` and `async gen move {`. this.parse_gen_block() } else { this.parse_expr_closure() } - } else if this.eat_keyword(kw::Await) { + } else if this.token.uninterpolated_span().at_least_rust_2024() + && (this.is_gen_block(kw::Gen, 0) + || (this.check_keyword(kw::Async) && this.is_gen_block(kw::Gen, 1))) + { + this.parse_gen_block() + } else if this.eat_keyword_noexpect(kw::Await) { this.recover_incorrect_await_syntax(lo, this.prev_token.span) - } else if this.token.uninterpolated_span().at_least_rust_2024() { - if this.is_gen_block(kw::Gen) { - this.parse_gen_block() - } else { - this.parse_expr_lit() - } } else { this.parse_expr_lit() } @@ -2234,8 +2235,8 @@ impl<'a> Parser<'a> { let movability = if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; - let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() { - self.parse_asyncness(Case::Sensitive) + let coroutine_kind = if self.token.uninterpolated_span().at_least_rust_2018() { + self.parse_coroutine_kind(Case::Sensitive) } else { None }; @@ -2261,9 +2262,17 @@ impl<'a> Parser<'a> { } }; - if let Some(CoroutineKind::Async { span, .. }) = asyncness { - // Feature-gate `async ||` closures. - self.sess.gated_spans.gate(sym::async_closure, span); + match coroutine_kind { + Some(CoroutineKind::Async { span, .. }) => { + // Feature-gate `async ||` closures. + self.sess.gated_spans.gate(sym::async_closure, span); + } + Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => { + // Feature-gate `gen ||` and `async gen ||` closures. + // FIXME(gen_blocks): This perhaps should be a different gate. + self.sess.gated_spans.gate(sym::gen_blocks, span); + } + None => {} } if self.token.kind == TokenKind::Semi @@ -2284,7 +2293,7 @@ impl<'a> Parser<'a> { binder, capture_clause, constness, - coro_kind: asyncness, + coroutine_kind, movability, fn_decl, body, @@ -2899,127 +2908,155 @@ impl<'a> Parser<'a> { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; let (pat, guard) = this.parse_match_arm_pat_and_guard()?; - let arrow_span = this.token.span; - if let Err(mut err) = this.expect(&token::FatArrow) { - // We might have a `=>` -> `=` or `->` typo (issue #89396). - if TokenKind::FatArrow - .similar_tokens() - .is_some_and(|similar_tokens| similar_tokens.contains(&this.token.kind)) - { - err.span_suggestion( - this.token.span, - "use a fat arrow to start a match arm", - "=>", - Applicability::MachineApplicable, - ); - if matches!( - (&this.prev_token.kind, &this.token.kind), - (token::DotDotEq, token::Gt) - ) { - // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`, - // so we suppress the error here - err.delay_as_bug(); + + let span_before_body = this.prev_token.span; + let arm_body; + let is_fat_arrow = this.check(&token::FatArrow); + let is_almost_fat_arrow = TokenKind::FatArrow + .similar_tokens() + .is_some_and(|similar_tokens| similar_tokens.contains(&this.token.kind)); + let mut result = if !is_fat_arrow && !is_almost_fat_arrow { + // A pattern without a body, allowed for never patterns. + arm_body = None; + this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]) + } else { + if let Err(mut err) = this.expect(&token::FatArrow) { + // We might have a `=>` -> `=` or `->` typo (issue #89396). + if is_almost_fat_arrow { + err.span_suggestion( + this.token.span, + "use a fat arrow to start a match arm", + "=>", + Applicability::MachineApplicable, + ); + if matches!( + (&this.prev_token.kind, &this.token.kind), + (token::DotDotEq, token::Gt) + ) { + // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`, + // so we suppress the error here + err.delay_as_bug(); + } else { + err.emit(); + } + this.bump(); } else { - err.emit(); + return Err(err); } - this.bump(); - } else { - return Err(err); } - } - let arm_start_span = this.token.span; + let arrow_span = this.prev_token.span; + let arm_start_span = this.token.span; - let expr = this.parse_expr_res(Restrictions::STMT_EXPR, None).map_err(|mut err| { - err.span_label(arrow_span, "while parsing the `match` arm starting here"); - err - })?; + let expr = + this.parse_expr_res(Restrictions::STMT_EXPR, None).map_err(|mut err| { + err.span_label(arrow_span, "while parsing the `match` arm starting here"); + err + })?; - let require_comma = classify::expr_requires_semi_to_be_stmt(&expr) - && this.token != token::CloseDelim(Delimiter::Brace); - - let hi = this.prev_token.span; - - if require_comma { - let sm = this.sess.source_map(); - if let Some(body) = this.parse_arm_body_missing_braces(&expr, arrow_span) { - let span = body.span; - return Ok(( - ast::Arm { - attrs, - pat, - guard, - body, - span, - id: DUMMY_NODE_ID, - is_placeholder: false, - }, - TrailingToken::None, - )); - } - this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]) - .or_else(|mut err| { - if this.token == token::FatArrow { - if let Ok(expr_lines) = sm.span_to_lines(expr.span) - && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span) - && arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col - && expr_lines.lines.len() == 2 - { - // We check whether there's any trailing code in the parse span, - // if there isn't, we very likely have the following: - // - // X | &Y => "y" - // | -- - missing comma - // | | - // | arrow_span - // X | &X => "x" - // | - ^^ self.token.span - // | | - // | parsed until here as `"y" & X` - err.span_suggestion_short( - arm_start_span.shrink_to_hi(), - "missing a comma here to end this `match` arm", - ",", - Applicability::MachineApplicable, + let require_comma = classify::expr_requires_semi_to_be_stmt(&expr) + && this.token != token::CloseDelim(Delimiter::Brace); + + if !require_comma { + arm_body = Some(expr); + this.eat(&token::Comma); + Ok(false) + } else if let Some(body) = this.parse_arm_body_missing_braces(&expr, arrow_span) { + arm_body = Some(body); + Ok(true) + } else { + let expr_span = expr.span; + arm_body = Some(expr); + this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]) + .map_err(|mut err| { + if this.token == token::FatArrow { + let sm = this.sess.source_map(); + if let Ok(expr_lines) = sm.span_to_lines(expr_span) + && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span) + && arm_start_lines.lines[0].end_col + == expr_lines.lines[0].end_col + && expr_lines.lines.len() == 2 + { + // We check whether there's any trailing code in the parse span, + // if there isn't, we very likely have the following: + // + // X | &Y => "y" + // | -- - missing comma + // | | + // | arrow_span + // X | &X => "x" + // | - ^^ self.token.span + // | | + // | parsed until here as `"y" & X` + err.span_suggestion_short( + arm_start_span.shrink_to_hi(), + "missing a comma here to end this `match` arm", + ",", + Applicability::MachineApplicable, + ); + } + } else { + err.span_label( + arrow_span, + "while parsing the `match` arm starting here", ); - return Err(err); } - } else { - // FIXME(compiler-errors): We could also recover `; PAT =>` here - - // Try to parse a following `PAT =>`, if successful - // then we should recover. - let mut snapshot = this.create_snapshot_for_diagnostic(); - let pattern_follows = snapshot - .parse_pat_allow_top_alt( - None, - RecoverComma::Yes, - RecoverColon::Yes, - CommaRecoveryMode::EitherTupleOrPipe, - ) - .map_err(|err| err.cancel()) - .is_ok(); - if pattern_follows && snapshot.check(&TokenKind::FatArrow) { - err.cancel(); - this.sess.emit_err(errors::MissingCommaAfterMatchArm { - span: hi.shrink_to_hi(), - }); - return Ok(true); - } - } - err.span_label(arrow_span, "while parsing the `match` arm starting here"); - Err(err) - })?; - } else { - this.eat(&token::Comma); + err + }) + } + }; + + let hi_span = arm_body.as_ref().map_or(span_before_body, |body| body.span); + let arm_span = lo.to(hi_span); + + // We want to recover: + // X | Some(_) => foo() + // | - missing comma + // X | None => "x" + // | ^^^^ self.token.span + // as well as: + // X | Some(!) + // | - missing comma + // X | None => "x" + // | ^^^^ self.token.span + // But we musn't recover + // X | pat[0] => {} + // | ^ self.token.span + let recover_missing_comma = arm_body.is_some() || pat.could_be_never_pattern(); + if recover_missing_comma { + result = result.or_else(|err| { + // FIXME(compiler-errors): We could also recover `; PAT =>` here + + // Try to parse a following `PAT =>`, if successful + // then we should recover. + let mut snapshot = this.create_snapshot_for_diagnostic(); + let pattern_follows = snapshot + .parse_pat_allow_top_alt( + None, + RecoverComma::Yes, + RecoverColon::Yes, + CommaRecoveryMode::EitherTupleOrPipe, + ) + .map_err(|err| err.cancel()) + .is_ok(); + if pattern_follows && snapshot.check(&TokenKind::FatArrow) { + err.cancel(); + this.sess.emit_err(errors::MissingCommaAfterMatchArm { + span: arm_span.shrink_to_hi(), + }); + return Ok(true); + } + Err(err) + }); } + result?; Ok(( ast::Arm { attrs, pat, guard, - body: expr, - span: lo.to(hi), + body: arm_body, + span: arm_span, id: DUMMY_NODE_ID, is_placeholder: false, }, @@ -3179,7 +3216,7 @@ impl<'a> Parser<'a> { fn parse_gen_block(&mut self) -> PResult<'a, P<Expr>> { let lo = self.token.span; let kind = if self.eat_keyword(kw::Async) { - GenBlockKind::Async + if self.eat_keyword(kw::Gen) { GenBlockKind::AsyncGen } else { GenBlockKind::Async } } else { assert!(self.eat_keyword(kw::Gen)); self.sess.gated_spans.gate(sym::gen_blocks, lo.to(self.token.span)); @@ -3191,22 +3228,26 @@ impl<'a> Parser<'a> { Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs)) } - fn is_gen_block(&self, kw: Symbol) -> bool { - self.token.is_keyword(kw) + fn is_gen_block(&self, kw: Symbol, lookahead: usize) -> bool { + self.is_keyword_ahead(lookahead, &[kw]) && (( // `async move {` - self.is_keyword_ahead(1, &[kw::Move]) - && self.look_ahead(2, |t| { + self.is_keyword_ahead(lookahead + 1, &[kw::Move]) + && self.look_ahead(lookahead + 2, |t| { *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block() }) ) || ( // `async {` - self.look_ahead(1, |t| { + self.look_ahead(lookahead + 1, |t| { *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block() }) )) } + pub(super) fn is_async_gen_block(&self) -> bool { + self.token.is_keyword(kw::Async) && self.is_gen_block(kw::Gen, 1) + } + fn is_certainly_not_a_block(&self) -> bool { self.look_ahead(1, |t| t.is_ident()) && ( diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 086e8d5cf9b..d22cc04d182 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2359,8 +2359,10 @@ impl<'a> Parser<'a> { || case == Case::Insensitive && t.is_non_raw_ident_where(|i| quals.iter().any(|qual| qual.as_str() == i.name.as_str().to_lowercase())) ) - // Rule out unsafe extern block. - && !self.is_unsafe_foreign_mod()) + // Rule out `unsafe extern {`. + && !self.is_unsafe_foreign_mod() + // Rule out `async gen {` and `async gen move {` + && !self.is_async_gen_block()) }) // `extern ABI fn` || self.check_keyword_case(kw::Extern, case) @@ -2392,10 +2394,7 @@ impl<'a> Parser<'a> { let constness = self.parse_constness(case); let async_start_sp = self.token.span; - let asyncness = self.parse_asyncness(case); - - let _gen_start_sp = self.token.span; - let genness = self.parse_genness(case); + let coroutine_kind = self.parse_coroutine_kind(case); let unsafe_start_sp = self.token.span; let unsafety = self.parse_unsafety(case); @@ -2403,7 +2402,7 @@ impl<'a> Parser<'a> { let ext_start_sp = self.token.span; let ext = self.parse_extern(case); - if let Some(CoroutineKind::Async { span, .. }) = asyncness { + if let Some(CoroutineKind::Async { span, .. }) = coroutine_kind { if span.is_rust_2015() { self.sess.emit_err(errors::AsyncFnIn2015 { span, @@ -2412,16 +2411,11 @@ impl<'a> Parser<'a> { } } - if let Some(CoroutineKind::Gen { span, .. }) = genness { - self.sess.gated_spans.gate(sym::gen_blocks, span); - } - - if let ( - Some(CoroutineKind::Async { span: async_span, .. }), - Some(CoroutineKind::Gen { span: gen_span, .. }), - ) = (asyncness, genness) - { - self.sess.emit_err(errors::AsyncGenFn { span: async_span.to(gen_span) }); + match coroutine_kind { + Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => { + self.sess.gated_spans.gate(sym::gen_blocks, span); + } + Some(CoroutineKind::Async { .. }) | None => {} } if !self.eat_keyword_case(kw::Fn, case) { @@ -2440,7 +2434,7 @@ impl<'a> Parser<'a> { // We may be able to recover let mut recover_constness = constness; - let mut recover_asyncness = asyncness; + let mut recover_coroutine_kind = coroutine_kind; let mut recover_unsafety = unsafety; // This will allow the machine fix to directly place the keyword in the correct place or to indicate // that the keyword is already present and the second instance should be removed. @@ -2453,15 +2447,24 @@ impl<'a> Parser<'a> { } } } else if self.check_keyword(kw::Async) { - match asyncness { + match coroutine_kind { Some(CoroutineKind::Async { span, .. }) => { Some(WrongKw::Duplicated(span)) } + Some(CoroutineKind::AsyncGen { span, .. }) => { + Some(WrongKw::Duplicated(span)) + } Some(CoroutineKind::Gen { .. }) => { - panic!("not sure how to recover here") + recover_coroutine_kind = Some(CoroutineKind::AsyncGen { + span: self.token.span, + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, + }); + // FIXME(gen_blocks): This span is wrong, didn't want to think about it. + Some(WrongKw::Misplaced(unsafe_start_sp)) } None => { - recover_asyncness = Some(CoroutineKind::Async { + recover_coroutine_kind = Some(CoroutineKind::Async { span: self.token.span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID, @@ -2559,7 +2562,7 @@ impl<'a> Parser<'a> { return Ok(FnHeader { constness: recover_constness, unsafety: recover_unsafety, - coro_kind: recover_asyncness, + coroutine_kind: recover_coroutine_kind, ext, }); } @@ -2569,13 +2572,7 @@ impl<'a> Parser<'a> { } } - let coro_kind = match asyncness { - Some(CoroutineKind::Async { .. }) => asyncness, - Some(CoroutineKind::Gen { .. }) => unreachable!("asycness cannot be Gen"), - None => genness, - }; - - Ok(FnHeader { constness, unsafety, coro_kind, ext }) + Ok(FnHeader { constness, unsafety, coroutine_kind, ext }) } /// Parses the parameter list and result type of a function declaration. diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 2816386cbad..7a306823ed4 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1125,23 +1125,30 @@ impl<'a> Parser<'a> { } /// Parses asyncness: `async` or nothing. - fn parse_asyncness(&mut self, case: Case) -> Option<CoroutineKind> { + fn parse_coroutine_kind(&mut self, case: Case) -> Option<CoroutineKind> { + let span = self.token.uninterpolated_span(); if self.eat_keyword_case(kw::Async, case) { - let span = self.prev_token.uninterpolated_span(); - Some(CoroutineKind::Async { - span, - closure_id: DUMMY_NODE_ID, - return_impl_trait_id: DUMMY_NODE_ID, - }) - } else { - None - } - } - - /// Parses genness: `gen` or nothing. - fn parse_genness(&mut self, case: Case) -> Option<CoroutineKind> { - if self.token.span.at_least_rust_2024() && self.eat_keyword_case(kw::Gen, case) { - let span = self.prev_token.uninterpolated_span(); + // FIXME(gen_blocks): Do we want to unconditionally parse `gen` and then + // error if edition <= 2024, like we do with async and edition <= 2018? + if self.token.uninterpolated_span().at_least_rust_2024() + && self.eat_keyword_case(kw::Gen, case) + { + let gen_span = self.prev_token.uninterpolated_span(); + Some(CoroutineKind::AsyncGen { + span: span.to(gen_span), + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, + }) + } else { + Some(CoroutineKind::Async { + span, + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, + }) + } + } else if self.token.uninterpolated_span().at_least_rust_2024() + && self.eat_keyword_case(kw::Gen, case) + { Some(CoroutineKind::Gen { span, closure_id: DUMMY_NODE_ID, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index bd1bf2c7859..020b66a985a 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -154,12 +154,8 @@ impl<'a> Parser<'a> { } Err(err) => return Err(err), }; - if rc == RecoverComma::Yes { - self.maybe_recover_unexpected_comma( - first_pat.span, - matches!(first_pat.kind, PatKind::MacCall(_)), - rt, - )?; + if rc == RecoverComma::Yes && !first_pat.could_be_never_pattern() { + self.maybe_recover_unexpected_comma(first_pat.span, rt)?; } // If the next token is not a `|`, @@ -200,8 +196,8 @@ impl<'a> Parser<'a> { err.span_label(lo, WHILE_PARSING_OR_MSG); err })?; - if rc == RecoverComma::Yes { - self.maybe_recover_unexpected_comma(pat.span, false, rt)?; + if rc == RecoverComma::Yes && !pat.could_be_never_pattern() { + self.maybe_recover_unexpected_comma(pat.span, rt)?; } pats.push(pat); } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index f349140e8c3..da8cc05ff66 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -598,7 +598,7 @@ impl<'a> Parser<'a> { tokens: None, }; let span_start = self.token.span; - let ast::FnHeader { ext, unsafety, constness, coro_kind } = + let ast::FnHeader { ext, unsafety, constness, coroutine_kind } = self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?; if self.may_recover() && self.token.kind == TokenKind::Lt { self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?; @@ -611,7 +611,7 @@ impl<'a> Parser<'a> { // cover it. self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span }); } - if let Some(ast::CoroutineKind::Async { span, .. }) = coro_kind { + if let Some(ast::CoroutineKind::Async { span, .. }) = coroutine_kind { self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span }); } // FIXME(gen_blocks): emit a similar error for `gen fn()` |
