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