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