1use ast::token::IdentIsRaw;
2use rustc_ast as ast;
3use rustc_ast::ast::*;
4use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, TokenKind};
5use rustc_ast::tokenstream::TokenTree;
6use rustc_ast::util::case::Case;
7use rustc_ast_pretty::pprust;
8use rustc_errors::{Applicability, PResult};
9use rustc_session::lint::builtin::VARARGS_WITHOUT_PATTERN;
10use rustc_span::edition::Edition;
11use rustc_span::{ErrorGuaranteed, Ident, Span, kw, respan, sym};
12use thin_vec::ThinVec;
13use tracing::debug;
14
15use super::diagnostics::dummy_arg;
16use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
17use super::{
18 ExpKeywordPair, FollowedByType, ForceCollect, Parser, Recovered, Trailing, UsePreAttrPos,
19};
20use crate::diagnostics::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst};
21use crate::exp;
22
23type ReqName = fn(Edition, IsDotDotDot) -> bool;
32
33#[derive(#[automatically_derived]
impl ::core::marker::Copy for IsDotDotDot { }Copy, #[automatically_derived]
impl ::core::clone::Clone for IsDotDotDot {
#[inline]
fn clone(&self) -> IsDotDotDot { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for IsDotDotDot {
#[inline]
fn eq(&self, other: &IsDotDotDot) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
34pub(crate) enum IsDotDotDot {
35 Yes,
36 No,
37}
38
39#[derive(#[automatically_derived]
impl ::core::clone::Clone for FnParseMode {
#[inline]
fn clone(&self) -> FnParseMode {
let _: ::core::clone::AssertParamIsClone<ReqName>;
let _: ::core::clone::AssertParamIsClone<FnContext>;
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FnParseMode { }Copy)]
47pub(crate) struct FnParseMode {
48 pub(super) req_name: ReqName,
74 pub(super) context: FnContext,
77 pub(super) req_body: bool,
96}
97
98#[derive(#[automatically_derived]
impl ::core::clone::Clone for FnContext {
#[inline]
fn clone(&self) -> FnContext { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FnContext { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for FnContext {
#[inline]
fn eq(&self, other: &FnContext) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FnContext {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
101pub(crate) enum FnContext {
102 Free,
104 FunctionPtrType,
106 Trait,
108 Impl,
110}
111
112impl<'a> Parser<'a> {
114 pub(super) fn parse_fn(
116 &mut self,
117 attrs: &mut AttrVec,
118 fn_parse_mode: FnParseMode,
119 sig_lo: Span,
120 vis: &Visibility,
121 case: Case,
122 ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
123 let fn_span = self.token.span;
124 let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; let decl = match self.parse_fn_decl(&fn_parse_mode, AllowPlus::Yes, RecoverReturnSign::Yes)
128 {
129 Ok(decl) => decl,
130 Err(old_err) => {
131 if self.token.is_keyword(kw::For) {
133 old_err.cancel();
134 return Err(self.dcx().create_err(diagnostics::FnTypoWithImpl { fn_span }));
135 } else {
136 return Err(old_err);
137 }
138 }
139 };
140
141 let fn_params_end = self.prev_token.span.shrink_to_hi();
144
145 let contract = self.parse_contract()?;
146
147 generics.where_clause = self.parse_where_clause()?; let fn_params_end =
151 if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
152
153 let mut sig_hi = self.prev_token.span;
154 let body =
156 self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
157 let fn_sig_span = sig_lo.to(sig_hi);
158 Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
159 }
160
161 fn error_fn_body_not_found(
163 &mut self,
164 ident_span: Span,
165 req_body: bool,
166 fn_params_end: Option<Span>,
167 ) -> PResult<'a, ErrorGuaranteed> {
168 let expected: &[_] =
169 if req_body { &[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)] } else { &[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)] };
170 match self.expected_one_of_not_found(&[], expected) {
171 Ok(error_guaranteed) => Ok(error_guaranteed),
172 Err(mut err) => {
173 if self.token == token::CloseBrace {
174 err.span_label(ident_span, "while parsing this `fn`");
177 Ok(err.emit())
178 } else if self.token == token::RArrow
179 && let Some(fn_params_end) = fn_params_end
180 {
181 let fn_trait_span =
187 [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
188 if self.prev_token.is_ident_named(symbol) {
189 Some(self.prev_token.span)
190 } else {
191 None
192 }
193 });
194
195 let arrow_span = self.token.span;
200 let ty_span = match self.parse_ret_ty(
201 AllowPlus::Yes,
202 RecoverQPath::Yes,
203 RecoverReturnSign::Yes,
204 ) {
205 Ok(ty_span) => ty_span.span().shrink_to_hi(),
206 Err(parse_error) => {
207 parse_error.cancel();
208 return Err(err);
209 }
210 };
211 let ret_ty_span = arrow_span.to(ty_span);
212
213 if let Some(fn_trait_span) = fn_trait_span {
214 err.subdiagnostic(diagnostics::FnTraitMissingParen { span: fn_trait_span });
217 } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
218 {
219 err.primary_message(
223 "return type should be specified after the function parameters",
224 );
225 err.subdiagnostic(diagnostics::MisplacedReturnType {
226 fn_params_end,
227 snippet,
228 ret_ty_span,
229 });
230 }
231 Err(err)
232 } else {
233 Err(err)
234 }
235 }
236 }
237 }
238
239 fn parse_fn_body(
243 &mut self,
244 attrs: &mut AttrVec,
245 ident: &Ident,
246 sig_hi: &mut Span,
247 req_body: bool,
248 fn_params_end: Option<Span>,
249 ) -> PResult<'a, Option<Box<Block>>> {
250 let has_semi = if req_body {
251 self.token == TokenKind::Semi
252 } else {
253 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))
255 };
256 let (inner_attrs, body) = if has_semi {
257 self.expect_semi()?;
259 *sig_hi = self.prev_token.span;
260 (AttrVec::new(), None)
261 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) || self.token.is_metavar_block() {
262 let prev_in_fn_body = self.in_fn_body;
263 self.in_fn_body = true;
264 let res = self.parse_block_common(self.token.span, BlockCheckMode::Default, None).map(
265 |(attrs, mut body)| {
266 if let Some(guar) = self.fn_body_missing_semi_guar.take() {
267 body.stmts.push(self.mk_stmt(
268 body.span,
269 StmtKind::Expr(self.mk_expr(body.span, ExprKind::Err(guar))),
270 ));
271 }
272 (attrs, Some(body))
273 },
274 );
275 self.in_fn_body = prev_in_fn_body;
276 res?
277 } else if self.token == token::Eq {
278 self.bump(); let eq_sp = self.prev_token.span;
281 let _ = self.parse_expr()?;
282 self.expect_semi()?; let span = eq_sp.to(self.prev_token.span);
284 let guar = self.dcx().emit_err(diagnostics::FunctionBodyEqualsExpr {
285 span,
286 sugg: diagnostics::FunctionBodyEqualsExprSugg {
287 eq: eq_sp,
288 semi: self.prev_token.span,
289 },
290 });
291 (AttrVec::new(), Some(self.mk_block_err(span, guar)))
292 } else {
293 self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
294 (AttrVec::new(), None)
295 };
296 attrs.extend(inner_attrs);
297 Ok(body)
298 }
299
300 pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
305 const ALL_QUALS: &[ExpKeywordPair] = &[
306 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub),
307 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen),
308 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const),
309 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async),
310 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe),
311 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe),
312 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern),
313 ];
314
315 let quals: &[_] = if check_pub {
320 ALL_QUALS
321 } else {
322 &[crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern)]
323 };
324 self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Fn,
token_type: crate::parser::token_type::TokenType::KwFn,
}exp!(Fn), case) || quals.iter().any(|&exp| self.check_keyword_case(exp, case))
327 && self.look_ahead(1, |t| {
328 t.is_keyword_case(kw::Fn, case)
330 || (
332 (
333 t.is_non_raw_ident_where(|i|
334 quals.iter().any(|exp| exp.kw == i.name)
335 && i.is_reserved()
337 )
338 || case == Case::Insensitive
339 && t.is_non_raw_ident_where(|i| quals.iter().any(|exp| {
340 exp.kw.as_str() == i.name.as_str().to_lowercase()
341 }))
342 )
343 && !self.is_unsafe_foreign_mod()
345 && !self.is_async_gen_block()
347 && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait, kw::Impl])
349 )
350 })
351 || self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern), case)
353 && self.look_ahead(1, |t| t.can_begin_string_literal())
357 && (self.tree_look_ahead(2, |tt| {
358 match tt {
359 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
360 TokenTree::Delimited(..) => false,
361 }
362 }) == Some(true) ||
363 (self.may_recover()
366 && self.tree_look_ahead(2, |tt| {
367 match tt {
368 TokenTree::Token(t, _) =>
369 ALL_QUALS.iter().any(|exp| {
370 t.is_keyword(exp.kw)
371 }),
372 TokenTree::Delimited(..) => false,
373 }
374 }) == Some(true)
375 && self.tree_look_ahead(3, |tt| {
376 match tt {
377 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
378 TokenTree::Delimited(..) => false,
379 }
380 }) == Some(true)
381 )
382 )
383 }
384
385 pub(super) fn parse_fn_front_matter(
400 &mut self,
401 orig_vis: &Visibility,
402 case: Case,
403 parsing_mode: FrontMatterParsingMode,
404 ) -> PResult<'a, FnHeader> {
405 let sp_start = self.token.span;
406 let constness = self.parse_constness(case);
407 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
408 && let Const::Yes(const_span) = constness
409 {
410 self.dcx().emit_err(FnPointerCannotBeConst {
411 span: const_span,
412 suggestion: const_span.until(self.token.span),
413 });
414 }
415
416 let async_start_sp = self.token.span;
417 let coroutine_marker = self.parse_coroutine_marker(case);
418 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
419 && let Some(coroutine_marker) = coroutine_marker
420 && coroutine_marker.kind == CoroutineKind::Async
421 {
422 self.dcx().emit_err(FnPointerCannotBeAsync {
423 span: coroutine_marker.span,
424 suggestion: coroutine_marker.span.until(self.token.span),
425 });
426 }
427 let unsafe_start_sp = self.token.span;
430 let safety = self.parse_safety(case);
431
432 let ext_start_sp = self.token.span;
433 let ext = self.parse_extern(case);
434
435 if let Some(coroutine_marker) = coroutine_marker
436 && let CoroutineKind::Async = coroutine_marker.kind
437 && coroutine_marker.span.is_rust_2015()
438 {
439 self.dcx().emit_err(diagnostics::AsyncFnIn2015 {
440 span: coroutine_marker.span,
441 help: diagnostics::HelpUseLatestEdition::new(),
442 });
443 }
444
445 if let Some(coroutine_marker) = coroutine_marker
446 && coroutine_marker.kind.is_gen()
447 {
448 self.psess.gated_spans.gate(sym::gen_blocks, coroutine_marker.span);
449 }
450
451 if !self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Fn,
token_type: crate::parser::token_type::TokenType::KwFn,
}exp!(Fn), case) {
452 match self.expect_one_of(&[], &[]) {
456 Ok(Recovered::Yes(_)) => {}
457 Ok(Recovered::No) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
458 Err(mut err) => {
459 enum WrongKw {
461 Duplicated(Span),
462 Misplaced(Span),
463 MisplacedDisallowedQualifier,
468 }
469
470 let mut recover_constness = constness;
472 let mut recover_coroutine_marker = coroutine_marker;
473 let mut recover_safety = safety;
474 let wrong_kw = if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) {
477 match constness {
478 Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
479 Const::No => {
480 recover_constness = Const::Yes(self.token.span);
481 match parsing_mode {
482 FrontMatterParsingMode::Function => {
483 Some(WrongKw::Misplaced(async_start_sp))
484 }
485 FrontMatterParsingMode::FunctionPtrType => {
486 self.dcx().emit_err(FnPointerCannotBeConst {
487 span: self.token.span,
488 suggestion: self
489 .token
490 .span
491 .with_lo(self.prev_token.span.hi()),
492 });
493 Some(WrongKw::MisplacedDisallowedQualifier)
494 }
495 }
496 }
497 }
498 } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async)) {
499 match coroutine_marker {
500 Some(CoroutineMarker {
501 kind: CoroutineKind::Async | CoroutineKind::AsyncGen,
502 span,
503 ..
504 }) => Some(WrongKw::Duplicated(span)),
505 Some(CoroutineMarker { kind: CoroutineKind::Gen, .. }) => {
506 recover_coroutine_marker = Some(CoroutineMarker::new(
507 CoroutineKind::AsyncGen,
508 self.token.span,
509 ));
510 Some(WrongKw::Misplaced(unsafe_start_sp))
512 }
513 None => {
514 recover_coroutine_marker = Some(CoroutineMarker::new(
515 CoroutineKind::Async,
516 self.token.span,
517 ));
518 match parsing_mode {
519 FrontMatterParsingMode::Function => {
520 Some(WrongKw::Misplaced(async_start_sp))
521 }
522 FrontMatterParsingMode::FunctionPtrType => {
523 self.dcx().emit_err(FnPointerCannotBeAsync {
524 span: self.token.span,
525 suggestion: self
526 .token
527 .span
528 .with_lo(self.prev_token.span.hi()),
529 });
530 Some(WrongKw::MisplacedDisallowedQualifier)
531 }
532 }
533 }
534 }
535 } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe)) {
536 match safety {
537 Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
538 Safety::Safe(sp) => {
539 recover_safety = Safety::Unsafe(self.token.span);
540 Some(WrongKw::Misplaced(sp))
541 }
542 Safety::Default => {
543 recover_safety = Safety::Unsafe(self.token.span);
544 Some(WrongKw::Misplaced(ext_start_sp))
545 }
546 }
547 } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe)) {
548 match safety {
549 Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
550 Safety::Unsafe(sp) => {
551 recover_safety = Safety::Safe(self.token.span);
552 Some(WrongKw::Misplaced(sp))
553 }
554 Safety::Default => {
555 recover_safety = Safety::Safe(self.token.span);
556 Some(WrongKw::Misplaced(ext_start_sp))
557 }
558 }
559 } else {
560 None
561 };
562
563 if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw {
565 let original_kw = self
566 .span_to_snippet(original_sp)
567 .expect("Span extracted directly from keyword should always work");
568
569 err.span_suggestion_verbose(
570 self.token_uninterpolated_span(),
571 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` already used earlier, remove this one",
original_kw))
})format!("`{original_kw}` already used earlier, remove this one"),
572 "",
573 Applicability::MachineApplicable,
574 )
575 .span_note(original_sp, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` first seen here",
original_kw))
})format!("`{original_kw}` first seen here"));
576 }
577 else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
579 let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
580 if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
581 let misplaced_qual_sp = self.token_uninterpolated_span();
582 let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
583
584 err.span_suggestion_verbose(
585 correct_pos_sp.to(misplaced_qual_sp),
586 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` must come before `{1}`",
misplaced_qual, current_qual))
})format!("`{misplaced_qual}` must come before `{current_qual}`"),
587 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", misplaced_qual,
current_qual))
})format!("{misplaced_qual} {current_qual}"),
588 Applicability::MachineApplicable,
589 ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
590 }
591 }
592 else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub)) {
594 let sp = sp_start.to(self.prev_token.span);
595 if let Ok(snippet) = self.span_to_snippet(sp) {
596 let current_vis = match self.parse_visibility(FollowedByType::No) {
597 Ok(v) => v,
598 Err(d) => {
599 d.cancel();
600 return Err(err);
601 }
602 };
603 let vs = pprust::vis_to_string(¤t_vis);
604 let vs = vs.trim_end();
605
606 if #[allow(non_exhaustive_omitted_patterns)] match orig_vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(orig_vis.kind, VisibilityKind::Inherited) {
608 err.span_suggestion_verbose(
609 sp_start.to(self.prev_token.span),
610 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("visibility `{0}` must come before `{1}`",
vs, snippet))
})format!("visibility `{vs}` must come before `{snippet}`"),
611 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", vs, snippet))
})format!("{vs} {snippet}"),
612 Applicability::MachineApplicable,
613 );
614 }
615 else {
617 err.span_suggestion_verbose(
618 current_vis.span,
619 "there is already a visibility modifier, remove one",
620 "",
621 Applicability::MachineApplicable,
622 )
623 .span_note(orig_vis.span, "explicit visibility first seen here");
624 }
625 }
626 }
627
628 if let Some(wrong_kw) = wrong_kw
631 && self.may_recover()
632 && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
633 {
634 self.bump();
636 self.bump();
637 if #[allow(non_exhaustive_omitted_patterns)] match wrong_kw {
WrongKw::MisplacedDisallowedQualifier => true,
_ => false,
}matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
640 err.cancel();
641 } else {
642 err.emit();
643 }
644 return Ok(FnHeader {
645 constness: recover_constness,
646 safety: recover_safety,
647 coroutine_marker: recover_coroutine_marker,
648 ext,
649 });
650 }
651
652 return Err(err);
653 }
654 }
655 }
656
657 Ok(FnHeader { constness, safety, coroutine_marker, ext })
658 }
659
660 pub(super) fn parse_fn_decl(
662 &mut self,
663 fn_parse_mode: &FnParseMode,
664 ret_allow_plus: AllowPlus,
665 recover_return_sign: RecoverReturnSign,
666 ) -> PResult<'a, Box<FnDecl>> {
667 Ok(Box::new(FnDecl {
668 inputs: self.parse_fn_params(fn_parse_mode)?,
669 output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
670 }))
671 }
672
673 pub(super) fn parse_fn_params(
675 &mut self,
676 fn_parse_mode: &FnParseMode,
677 ) -> PResult<'a, ThinVec<Param>> {
678 let mut first_param = true;
679 if self.token != TokenKind::OpenParen
681 && !self.token.is_keyword(kw::For)
683 {
684 self.dcx().emit_err(diagnostics::MissingFnParams {
686 span: self.prev_token.span.shrink_to_hi(),
687 });
688 return Ok(ThinVec::new());
689 }
690
691 let (mut params, _) = self.parse_paren_comma_seq(|p| {
692 p.recover_vcs_conflict_marker();
693 let snapshot = p.create_snapshot_for_diagnostic();
694 let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| {
695 let guar = e.emit();
696 let lo = if let TokenKind::OpenParen = p.prev_token.kind {
700 p.prev_token.span.shrink_to_hi()
701 } else {
702 p.prev_token.span
703 };
704 p.restore_snapshot(snapshot);
705 p.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
707 Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
709 });
710 first_param = false;
712 param
713 })?;
714 self.deduplicate_recovered_params_names(&mut params);
716 Ok(params)
717 }
718
719 pub(super) fn parse_param_general(
724 &mut self,
725 fn_parse_mode: &FnParseMode,
726 first_param: bool,
727 recover_arg_parse: bool,
728 ) -> PResult<'a, Param> {
729 let lo = self.token.span;
730 let attrs = self.parse_outer_attributes()?;
731 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
732 if let Some(mut param) = this.parse_self_param()? {
734 param.attrs = attrs;
735 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
736 return Ok((res?, Trailing::No, UsePreAttrPos::No));
737 }
738
739 let is_dot_dot_dot = if this.token.kind == token::DotDotDot {
740 IsDotDotDot::Yes
741 } else {
742 IsDotDotDot::No
743 };
744 let is_name_required = (fn_parse_mode.req_name)(
745 this.token.span.with_neighbor(this.prev_token.span).edition(),
746 is_dot_dot_dot,
747 );
748 let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes {
749 this.psess.buffer_lint(
750 VARARGS_WITHOUT_PATTERN,
751 this.token.span,
752 ast::CRATE_NODE_ID,
753 diagnostics::VarargsWithoutPattern { span: this.token.span },
754 );
755 false
756 } else {
757 is_name_required
758 };
759 let (pat, ty) = if is_name_required || this.is_named_param() {
760 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_parse/src/parser/function.rs:760",
"rustc_parse::parser::function", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_parse/src/parser/function.rs"),
::tracing_core::__macro_support::Option::Some(760u32),
::tracing_core::__macro_support::Option::Some("rustc_parse::parser::function"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("parse_param_general parse_pat (is_name_required:{0})",
is_name_required) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
761 let (pat, colon) = this.parse_fn_param_pat_colon()?;
762 if !colon {
763 let mut err = this.unexpected().unwrap_err();
764 let pat_span = pat.span;
765 return if let Some(ident) = this.parameter_without_type(
766 &mut err,
767 pat,
768 is_name_required,
769 first_param,
770 fn_parse_mode,
771 ) {
772 let guar = err.emit();
773 let mut arg = dummy_arg(ident, guar);
774 arg.span = pat_span;
775 Ok((arg, Trailing::No, UsePreAttrPos::No))
776 } else {
777 Err(err)
778 };
779 }
780
781 this.eat_incorrect_doc_comment_for_param_type();
782 (pat, this.parse_ty_for_param()?)
783 } else {
784 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_parse/src/parser/function.rs:784",
"rustc_parse::parser::function", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_parse/src/parser/function.rs"),
::tracing_core::__macro_support::Option::Some(784u32),
::tracing_core::__macro_support::Option::Some("rustc_parse::parser::function"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("parse_param_general ident_to_pat")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("parse_param_general ident_to_pat");
785 let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
786 this.eat_incorrect_doc_comment_for_param_type();
787 let mut ty = this.parse_ty_for_param();
788
789 if let Ok(t) = &ty {
790 if let TyKind::Path(_, Path { segments, .. }) = &t.kind
792 && let Some(segment) = segments.last()
793 && let Some(guar) =
794 this.check_trailing_angle_brackets(segment, &[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)])
795 {
796 return Ok((
797 dummy_arg(segment.ident, guar),
798 Trailing::No,
799 UsePreAttrPos::No,
800 ));
801 }
802
803 if this.token != token::Comma && this.token != token::CloseParen {
804 ty = this.unexpected_any();
807 }
808 }
809 match ty {
810 Ok(ty) => {
811 let pat = this.mk_pat(ty.span, PatKind::Missing);
812 (Box::new(pat), ty)
813 }
814 Err(err) if this.token == token::DotDotDot => return Err(err),
816 Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
817 Err(err) if recover_arg_parse => {
818 err.cancel();
820 this.restore_snapshot(parser_snapshot_before_ty);
821 this.recover_arg_parse(fn_parse_mode.context)?
822 }
823 Err(err) => return Err(err),
824 }
825 };
826
827 let span = lo.to(this.prev_token.span);
828
829 Ok((
830 Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
831 Trailing::No,
832 UsePreAttrPos::No,
833 ))
834 })
835 }
836
837 fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
839 let expect_self_ident = |this: &mut Self| match this.token.ident() {
841 Some((ident, IdentIsRaw::No)) => {
842 this.bump();
843 ident
844 }
845 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
846 };
847 let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime());
849 let is_isolated_self = |this: &Self, n| {
851 this.is_keyword_ahead(n, &[kw::SelfLower])
852 && this.look_ahead(n + 1, |t| t != &token::PathSep)
853 };
854 let is_isolated_pin_const_self = |this: &Self, n| {
856 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
857 && this.is_keyword_ahead(n + 1, &[kw::Const])
858 && is_isolated_self(this, n + 2)
859 };
860 let is_isolated_mut_self =
862 |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
863 let is_isolated_pin_mut_self = |this: &Self, n| {
865 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
866 && is_isolated_mut_self(this, n + 1)
867 };
868 let parse_self_possibly_typed = |this: &mut Self, m| {
870 let eself_ident = expect_self_ident(this);
871 let eself_hi = this.prev_token.span;
872 let eself = if this.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) {
873 SelfKind::Explicit(this.parse_ty()?, m)
874 } else {
875 SelfKind::Value(m)
876 };
877 Ok((eself, eself_ident, eself_hi))
878 };
879 let expect_self_ident_not_typed =
880 |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
881 let eself_ident = expect_self_ident(this);
882
883 if this.may_recover() && this.eat_noexpect(&token::Colon) {
885 let snap = this.create_snapshot_for_diagnostic();
886 match this.parse_ty() {
887 Ok(ty) => {
888 this.dcx().emit_err(diagnostics::IncorrectTypeOnSelf {
889 span: ty.span,
890 move_self_modifier: diagnostics::MoveSelfModifier {
891 removal_span: modifier_span,
892 insertion_span: ty.span.shrink_to_lo(),
893 modifier: modifier.to_ref_suggestion(),
894 },
895 });
896 }
897 Err(diag) => {
898 diag.cancel();
899 this.restore_snapshot(snap);
900 }
901 }
902 }
903 eself_ident
904 };
905 let recover_self_ptr = |this: &mut Self| {
907 this.dcx().emit_err(diagnostics::SelfArgumentPointer { span: this.token.span });
908
909 Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
910 };
911
912 let eself_lo = self.token.span;
916 let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
917 token::And => {
918 let has_lifetime = is_lifetime(self, 1);
919 let skip_lifetime_count = has_lifetime as usize;
920 let eself = if is_isolated_self(self, skip_lifetime_count + 1) {
921 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
924 SelfKind::Region(lifetime, Mutability::Not)
925 } else if is_isolated_mut_self(self, skip_lifetime_count + 1) {
926 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
929 self.bump(); SelfKind::Region(lifetime, Mutability::Mut)
931 } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) {
932 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
935 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
936 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Not)
939 } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) {
940 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
943 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
944 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Mut)
947 } else {
948 return Ok(None);
950 };
951 let hi = self.token.span;
952 let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
953 (eself, self_ident, hi)
954 }
955 token::Star if is_isolated_self(self, 1) => {
957 self.bump();
958 recover_self_ptr(self)?
959 }
960 token::Star
962 if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
963 {
964 self.bump();
965 self.bump();
966 recover_self_ptr(self)?
967 }
968 token::Ident(..) if is_isolated_self(self, 0) => {
970 parse_self_possibly_typed(self, Mutability::Not)?
971 }
972 token::Ident(..) if is_isolated_mut_self(self, 0) => {
974 self.bump();
975 parse_self_possibly_typed(self, Mutability::Mut)?
976 }
977 _ => return Ok(None),
978 };
979
980 let eself = respan(eself_lo.to(eself_hi), eself);
981 Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
982 }
983
984 fn is_named_param(&self) -> bool {
985 let offset = match &self.token.kind {
986 token::OpenInvisible(origin) => match origin {
987 InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
988 return self.check_noexpect_past_close_delim(&token::Colon);
989 }
990 _ => 0,
991 },
992 token::And | token::AndAnd => 1,
993 _ if self.token.is_keyword(kw::Mut) => 1,
994 _ => 0,
995 };
996
997 self.look_ahead(offset, |t| t.is_ident())
998 && self.look_ahead(offset + 1, |t| t == &token::Colon)
999 }
1000
1001 pub(super) fn recover_self_param(&mut self) -> bool {
1002 #[allow(non_exhaustive_omitted_patterns)] match self.parse_outer_attributes().and_then(|_|
self.parse_self_param()).map_err(|e| e.cancel()) {
Ok(Some(_)) => true,
_ => false,
}matches!(
1003 self.parse_outer_attributes()
1004 .and_then(|_| self.parse_self_param())
1005 .map_err(|e| e.cancel()),
1006 Ok(Some(_))
1007 )
1008 }
1009}
1010
1011#[derive(#[automatically_derived]
impl ::core::marker::Copy for FrontMatterParsingMode { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FrontMatterParsingMode {
#[inline]
fn clone(&self) -> FrontMatterParsingMode { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for FrontMatterParsingMode {
#[inline]
fn eq(&self, other: &FrontMatterParsingMode) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FrontMatterParsingMode {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
1012pub(crate) enum FrontMatterParsingMode {
1013 Function,
1015 FunctionPtrType,
1018}