1use std::fmt::Write;
2use std::mem;
3
4use ast::token::IdentIsRaw;
5use rustc_ast::ast::*;
6use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
7use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
8use rustc_ast::util::case::Case;
9use rustc_ast::{
10 attr, {self as ast},
11};
12use rustc_ast_pretty::pprust;
13use rustc_errors::codes::*;
14use rustc_errors::{Applicability, PResult, StashKey, struct_span_code_err};
15use rustc_session::lint::builtin::VARARGS_WITHOUT_PATTERN;
16use rustc_span::edit_distance::edit_distance;
17use rustc_span::edition::Edition;
18use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, source_map, sym};
19use thin_vec::{ThinVec, thin_vec};
20use tracing::debug;
21
22use super::diagnostics::{ConsumeClosingDelim, dummy_arg};
23use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
24use super::{
25 AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect, Parser, PathStyle,
26 Recovered, Trailing, UsePreAttrPos,
27};
28use crate::errors::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField};
29use crate::{exp, fluent_generated as fluent};
30
31impl<'a> Parser<'a> {
32 pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
34 let (attrs, items, spans) = self.parse_mod(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eof,
token_type: crate::parser::token_type::TokenType::Eof,
}exp!(Eof))?;
35 Ok(ast::Crate { attrs, items, spans, id: DUMMY_NODE_ID, is_placeholder: false })
36 }
37
38 fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
40 let safety = self.parse_safety(Case::Sensitive);
41 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mod,
token_type: crate::parser::token_type::TokenType::KwMod,
}exp!(Mod))?;
42 let ident = self.parse_ident()?;
43 let mod_kind = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
44 ModKind::Unloaded
45 } else {
46 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
47 let (inner_attrs, items, inner_span) = self.parse_mod(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
48 attrs.extend(inner_attrs);
49 ModKind::Loaded(items, Inline::Yes, inner_span)
50 };
51 Ok(ItemKind::Mod(safety, ident, mod_kind))
52 }
53
54 pub fn parse_mod(
59 &mut self,
60 term: ExpTokenPair,
61 ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
62 let lo = self.token.span;
63 let attrs = self.parse_inner_attributes()?;
64
65 let post_attr_lo = self.token.span;
66 let mut items: ThinVec<Box<_>> = ThinVec::new();
67
68 loop {
71 while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} let Some(item) = self.parse_item(ForceCollect::No)? else {
73 break;
74 };
75 items.push(item);
76 }
77
78 if !self.eat(term) {
79 let token_str = super::token_descr(&self.token);
80 if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
81 let is_let = self.token.is_keyword(kw::Let);
82 let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
83 let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);
84
85 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected item, found {0}",
token_str))
})format!("expected item, found {token_str}");
86 let mut err = self.dcx().struct_span_err(self.token.span, msg);
87
88 let label = if is_let {
89 "`let` cannot be used for global variables"
90 } else {
91 "expected item"
92 };
93 err.span_label(self.token.span, label);
94
95 if is_let {
96 if is_let_mut {
97 err.help("consider using `static` and a `Mutex` instead of `let mut`");
98 } else if let_has_ident {
99 err.span_suggestion_short(
100 self.token.span,
101 "consider using `static` or `const` instead of `let`",
102 "static",
103 Applicability::MaybeIncorrect,
104 );
105 } else {
106 err.help("consider using `static` or `const` instead of `let`");
107 }
108 }
109 err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
110 return Err(err);
111 }
112 }
113
114 let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo());
115 let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };
116 Ok((attrs, items, mod_spans))
117 }
118}
119
120enum ReuseKind {
121 Path,
122 Impl,
123}
124
125impl<'a> Parser<'a> {
126 pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Box<Item>>> {
127 let fn_parse_mode =
128 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
129 self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(Box::new))
130 }
131
132 fn parse_item_(
133 &mut self,
134 fn_parse_mode: FnParseMode,
135 force_collect: ForceCollect,
136 ) -> PResult<'a, Option<Item>> {
137 self.recover_vcs_conflict_marker();
138 let attrs = self.parse_outer_attributes()?;
139 self.recover_vcs_conflict_marker();
140 self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect)
141 }
142
143 pub(super) fn parse_item_common(
144 &mut self,
145 attrs: AttrWrapper,
146 mac_allowed: bool,
147 attrs_allowed: bool,
148 fn_parse_mode: FnParseMode,
149 force_collect: ForceCollect,
150 ) -> PResult<'a, Option<Item>> {
151 if let Some(item) =
152 self.eat_metavar_seq(MetaVarKind::Item, |this| this.parse_item(ForceCollect::Yes))
153 {
154 let mut item = item.expect("an actual item");
155 attrs.prepend_to_nt_inner(&mut item.attrs);
156 return Ok(Some(*item));
157 }
158
159 self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {
160 let lo = this.token.span;
161 let vis = this.parse_visibility(FollowedByType::No)?;
162 let mut def = this.parse_defaultness();
163 let kind = this.parse_item_kind(
164 &mut attrs,
165 mac_allowed,
166 lo,
167 &vis,
168 &mut def,
169 fn_parse_mode,
170 Case::Sensitive,
171 )?;
172 if let Some(kind) = kind {
173 this.error_on_unconsumed_default(def, &kind);
174 let span = lo.to(this.prev_token.span);
175 let id = DUMMY_NODE_ID;
176 let item = Item { attrs, id, kind, vis, span, tokens: None };
177 return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
178 }
179
180 if !#[allow(non_exhaustive_omitted_patterns)] match vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(vis.kind, VisibilityKind::Inherited) {
182 this.dcx().emit_err(errors::VisibilityNotFollowedByItem { span: vis.span, vis });
183 }
184
185 if let Defaultness::Default(span) = def {
186 this.dcx().emit_err(errors::DefaultNotFollowedByItem { span });
187 }
188
189 if !attrs_allowed {
190 this.recover_attrs_no_item(&attrs)?;
191 }
192 Ok((None, Trailing::No, UsePreAttrPos::No))
193 })
194 }
195
196 fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
198 if let Defaultness::Default(span) = def {
199 self.dcx().emit_err(errors::InappropriateDefault {
200 span,
201 article: kind.article(),
202 descr: kind.descr(),
203 });
204 }
205 }
206
207 fn parse_item_kind(
209 &mut self,
210 attrs: &mut AttrVec,
211 macros_allowed: bool,
212 lo: Span,
213 vis: &Visibility,
214 def: &mut Defaultness,
215 fn_parse_mode: FnParseMode,
216 case: Case,
217 ) -> PResult<'a, Option<ItemKind>> {
218 let check_pub = def == &Defaultness::Final;
219 let mut def_ = || mem::replace(def, Defaultness::Final);
220
221 let info = if !self.is_use_closure() && self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Use,
token_type: crate::parser::token_type::TokenType::KwUse,
}exp!(Use), case) {
222 self.parse_use_item()?
223 } else if self.check_fn_front_matter(check_pub, case) {
224 let (ident, sig, generics, contract, body) =
226 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
227 ItemKind::Fn(Box::new(Fn {
228 defaultness: def_(),
229 ident,
230 sig,
231 generics,
232 contract,
233 body,
234 define_opaque: None,
235 eii_impls: ThinVec::new(),
236 }))
237 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern), case) {
238 if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Crate,
token_type: crate::parser::token_type::TokenType::KwCrate,
}exp!(Crate), case) {
239 self.parse_item_extern_crate()?
241 } else {
242 self.parse_item_foreign_mod(attrs, Safety::Default)?
244 }
245 } else if self.is_unsafe_foreign_mod() {
246 let safety = self.parse_safety(Case::Sensitive);
248 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern))?;
249 self.parse_item_foreign_mod(attrs, safety)?
250 } else if let Some(safety) = self.parse_global_static_front_matter(case) {
251 let mutability = self.parse_mutability();
253 self.parse_static_item(safety, mutability)?
254 } else if self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait), case) || self.check_trait_front_matter() {
255 self.parse_item_trait(attrs, lo)?
257 } else if self.check_impl_frontmatter(0) {
258 self.parse_item_impl(attrs, def_(), false)?
260 } else if let Const::Yes(const_span) = self.parse_constness(case) {
261 self.recover_const_mut(const_span);
263 self.recover_missing_kw_before_item()?;
264 let (ident, generics, ty, rhs) = self.parse_const_item(attrs)?;
265 ItemKind::Const(Box::new(ConstItem {
266 defaultness: def_(),
267 ident,
268 generics,
269 ty,
270 rhs,
271 define_opaque: None,
272 }))
273 } else if let Some(kind) = self.is_reuse_item() {
274 self.parse_item_delegation(attrs, def_(), kind)?
275 } else if self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mod,
token_type: crate::parser::token_type::TokenType::KwMod,
}exp!(Mod), case)
276 || self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe), case) && self.is_keyword_ahead(1, &[kw::Mod])
277 {
278 self.parse_item_mod(attrs)?
280 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Type,
token_type: crate::parser::token_type::TokenType::KwType,
}exp!(Type), case) {
281 self.parse_type_alias(def_())?
283 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Enum,
token_type: crate::parser::token_type::TokenType::KwEnum,
}exp!(Enum), case) {
284 self.parse_item_enum()?
286 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Struct,
token_type: crate::parser::token_type::TokenType::KwStruct,
}exp!(Struct), case) {
287 self.parse_item_struct()?
289 } else if self.is_kw_followed_by_ident(kw::Union) {
290 self.bump(); self.parse_item_union()?
293 } else if self.is_builtin() {
294 return self.parse_item_builtin();
296 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Macro,
token_type: crate::parser::token_type::TokenType::KwMacro,
}exp!(Macro), case) {
297 self.parse_item_decl_macro(lo)?
299 } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
300 self.parse_item_macro_rules(vis, has_bang)?
302 } else if self.isnt_macro_invocation()
303 && (self.token.is_ident_named(sym::import)
304 || self.token.is_ident_named(sym::using)
305 || self.token.is_ident_named(sym::include)
306 || self.token.is_ident_named(sym::require))
307 {
308 return self.recover_import_as_use();
309 } else if self.isnt_macro_invocation() && vis.kind.is_pub() {
310 self.recover_missing_kw_before_item()?;
311 return Ok(None);
312 } else if self.isnt_macro_invocation() && case == Case::Sensitive {
313 _ = def_;
314
315 return self.parse_item_kind(
317 attrs,
318 macros_allowed,
319 lo,
320 vis,
321 def,
322 fn_parse_mode,
323 Case::Insensitive,
324 );
325 } else if macros_allowed && self.check_path() {
326 if self.isnt_macro_invocation() {
327 self.recover_missing_kw_before_item()?;
328 }
329 ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
331 } else {
332 return Ok(None);
333 };
334 Ok(Some(info))
335 }
336
337 fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
338 let span = self.token.span;
339 let token_name = super::token_descr(&self.token);
340 let snapshot = self.create_snapshot_for_diagnostic();
341 self.bump();
342 match self.parse_use_item() {
343 Ok(u) => {
344 self.dcx().emit_err(errors::RecoverImportAsUse { span, token_name });
345 Ok(Some(u))
346 }
347 Err(e) => {
348 e.cancel();
349 self.restore_snapshot(snapshot);
350 Ok(None)
351 }
352 }
353 }
354
355 fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
356 let tree = self.parse_use_tree()?;
357 if let Err(mut e) = self.expect_semi() {
358 match tree.kind {
359 UseTreeKind::Glob => {
360 e.note("the wildcard token must be last on the path");
361 }
362 UseTreeKind::Nested { .. } => {
363 e.note("glob-like brace syntax must be last on the path");
364 }
365 _ => (),
366 }
367 return Err(e);
368 }
369 Ok(ItemKind::Use(tree))
370 }
371
372 pub(super) fn is_path_start_item(&mut self) -> bool {
374 self.is_kw_followed_by_ident(kw::Union) || self.is_reuse_item().is_some() || self.check_trait_front_matter() || self.is_async_fn() || #[allow(non_exhaustive_omitted_patterns)] match self.is_macro_rules_item() {
IsMacroRulesItem::Yes { .. } => true,
_ => false,
}matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) }
380
381 fn is_reuse_item(&mut self) -> Option<ReuseKind> {
382 if !self.token.is_keyword(kw::Reuse) {
383 return None;
384 }
385
386 if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
388 Some(ReuseKind::Path)
389 } else if self.check_impl_frontmatter(1) {
390 Some(ReuseKind::Impl)
391 } else {
392 None
393 }
394 }
395
396 fn isnt_macro_invocation(&mut self) -> bool {
398 self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
399 }
400
401 fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
404 let is_pub = self.prev_token.is_keyword(kw::Pub);
405 let is_const = self.prev_token.is_keyword(kw::Const);
406 let ident_span = self.token.span;
407 let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };
408 let insert_span = ident_span.shrink_to_lo();
409
410 let ident = if self.token.is_ident()
411 && self.token.is_non_reserved_ident()
412 && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
413 && self.look_ahead(1, |t| {
414 #[allow(non_exhaustive_omitted_patterns)] match t.kind {
token::Lt | token::OpenBrace | token::OpenParen => true,
_ => false,
}matches!(t.kind, token::Lt | token::OpenBrace | token::OpenParen)
415 }) {
416 self.parse_ident().unwrap()
417 } else {
418 return Ok(());
419 };
420
421 let mut found_generics = false;
422 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Lt,
token_type: crate::parser::token_type::TokenType::Lt,
}exp!(Lt)) {
423 found_generics = true;
424 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Gt,
token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)]);
425 self.bump(); }
427
428 let err = if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
429 if self.look_ahead(1, |t| *t == token::CloseBrace) {
431 Some(errors::MissingKeywordForItemDefinition::EnumOrStruct { span })
433 } else if self.look_ahead(2, |t| *t == token::Colon)
434 || self.look_ahead(3, |t| *t == token::Colon)
435 {
436 Some(errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident })
438 } else {
439 Some(errors::MissingKeywordForItemDefinition::Enum { span, insert_span, ident })
440 }
441 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
442 self.bump(); let is_method = self.recover_self_param();
445
446 self.consume_block(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen), ConsumeClosingDelim::Yes);
447
448 let err = if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::RArrow,
token_type: crate::parser::token_type::TokenType::RArrow,
}exp!(RArrow)) || self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
449 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)]);
450 self.bump(); self.consume_block(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), ConsumeClosingDelim::Yes);
452 if is_method {
453 errors::MissingKeywordForItemDefinition::Method { span, insert_span, ident }
454 } else {
455 errors::MissingKeywordForItemDefinition::Function { span, insert_span, ident }
456 }
457 } else if is_pub && self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
458 errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
459 } else {
460 errors::MissingKeywordForItemDefinition::Ambiguous {
461 span,
462 subdiag: if found_generics {
463 None
464 } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
465 Some(errors::AmbiguousMissingKwForItemSub::SuggestMacro {
466 span: ident_span,
467 snippet,
468 })
469 } else {
470 Some(errors::AmbiguousMissingKwForItemSub::HelpMacro)
471 },
472 }
473 };
474 Some(err)
475 } else if found_generics {
476 Some(errors::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
477 } else {
478 None
479 };
480
481 if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
482 }
483
484 fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
485 Ok(None)
487 }
488
489 fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
491 let path = self.parse_path(PathStyle::Mod)?; self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; match self.parse_delim_args() {
494 Ok(args) => {
496 self.eat_semi_for_macro_if_needed(&args);
497 self.complain_if_pub_macro(vis, false);
498 Ok(MacCall { path, args })
499 }
500
501 Err(mut err) => {
502 if self.token.is_ident()
504 && let [segment] = path.segments.as_slice()
505 && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
506 {
507 err.span_suggestion(
508 path.span,
509 "perhaps you meant to define a macro",
510 "macro_rules",
511 Applicability::MachineApplicable,
512 );
513 }
514 Err(err)
515 }
516 }
517 }
518
519 fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
521 let ([start @ end] | [start, .., end]) = attrs else {
522 return Ok(());
523 };
524 let msg = if end.is_doc_comment() {
525 "expected item after doc comment"
526 } else {
527 "expected item after attributes"
528 };
529 let mut err = self.dcx().struct_span_err(end.span, msg);
530 if end.is_doc_comment() {
531 err.span_label(end.span, "this doc comment doesn't document anything");
532 } else if self.token == TokenKind::Semi {
533 err.span_suggestion_verbose(
534 self.token.span,
535 "consider removing this semicolon",
536 "",
537 Applicability::MaybeIncorrect,
538 );
539 }
540 if let [.., penultimate, _] = attrs {
541 err.span_label(start.span.to(penultimate.span), "other attributes here");
542 }
543 Err(err)
544 }
545
546 fn is_async_fn(&self) -> bool {
547 self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
548 }
549
550 fn parse_polarity(&mut self) -> ast::ImplPolarity {
551 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) && self.look_ahead(1, |t| t.can_begin_type()) {
553 self.bump(); ast::ImplPolarity::Negative(self.prev_token.span)
555 } else {
556 ast::ImplPolarity::Positive
557 }
558 }
559
560 fn parse_item_impl(
575 &mut self,
576 attrs: &mut AttrVec,
577 defaultness: Defaultness,
578 is_reuse: bool,
579 ) -> PResult<'a, ItemKind> {
580 let mut constness = self.parse_constness(Case::Sensitive);
581 let safety = self.parse_safety(Case::Sensitive);
582 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
583
584 let mut generics = if self.choose_generics_over_qpath(0) {
586 self.parse_generics()?
587 } else {
588 let mut generics = Generics::default();
589 generics.span = self.prev_token.span.shrink_to_hi();
592 generics
593 };
594
595 if let Const::No = constness {
596 constness = self.parse_constness(Case::Sensitive);
598 }
599
600 if let Const::Yes(span) = constness {
601 self.psess.gated_spans.gate(sym::const_trait_impl, span);
602 }
603
604 if (self.token_uninterpolated_span().at_least_rust_2018()
606 && self.token.is_keyword(kw::Async))
607 || self.is_kw_followed_by_ident(kw::Async)
608 {
609 self.bump();
610 self.dcx().emit_err(errors::AsyncImpl { span: self.prev_token.span });
611 }
612
613 let polarity = self.parse_polarity();
614
615 let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
617 {
618 let span = self.prev_token.span.between(self.token.span);
619 return Err(self.dcx().create_err(errors::MissingTraitInTraitImpl {
620 span,
621 for_span: span.to(self.token.span),
622 }));
623 } else {
624 self.parse_ty_with_generics_recovery(&generics)?
625 };
626
627 let has_for = self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::For,
token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For));
629 let missing_for_span = self.prev_token.span.between(self.token.span);
630
631 let ty_second = if self.token == token::DotDot {
632 self.bump(); Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
639 } else if has_for || self.token.can_begin_type() {
640 Some(self.parse_ty()?)
641 } else {
642 None
643 };
644
645 generics.where_clause = self.parse_where_clause()?;
646
647 let impl_items = if is_reuse {
648 Default::default()
649 } else {
650 self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
651 };
652
653 let (of_trait, self_ty) = match ty_second {
654 Some(ty_second) => {
655 if !has_for {
657 self.dcx().emit_err(errors::MissingForInTraitImpl { span: missing_for_span });
658 }
659
660 let ty_first = *ty_first;
661 let path = match ty_first.kind {
662 TyKind::Path(None, path) => path,
664 other => {
665 if let TyKind::ImplTrait(_, bounds) = other
666 && let [bound] = bounds.as_slice()
667 && let GenericBound::Trait(poly_trait_ref) = bound
668 {
669 let extra_impl_kw = ty_first.span.until(bound.span());
673 self.dcx().emit_err(errors::ExtraImplKeywordInTraitImpl {
674 extra_impl_kw,
675 impl_trait_span: ty_first.span,
676 });
677 poly_trait_ref.trait_ref.path.clone()
678 } else {
679 return Err(self.dcx().create_err(
680 errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span },
681 ));
682 }
683 }
684 };
685 let trait_ref = TraitRef { path, ref_id: ty_first.id };
686
687 let of_trait =
688 Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
689 (of_trait, ty_second)
690 }
691 None => {
692 let self_ty = ty_first;
693 let error = |modifier, modifier_name, modifier_span| {
694 self.dcx().create_err(errors::TraitImplModifierInInherentImpl {
695 span: self_ty.span,
696 modifier,
697 modifier_name,
698 modifier_span,
699 self_ty: self_ty.span,
700 })
701 };
702
703 if let Safety::Unsafe(span) = safety {
704 error("unsafe", "unsafe", span).with_code(E0197).emit();
705 }
706 if let ImplPolarity::Negative(span) = polarity {
707 error("!", "negative", span).emit();
708 }
709 if let Defaultness::Default(def_span) = defaultness {
710 error("default", "default", def_span).emit();
711 }
712 if let Const::Yes(span) = constness {
713 self.psess.gated_spans.gate(sym::const_trait_impl, span);
714 }
715 (None, self_ty)
716 }
717 };
718
719 Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
720 }
721
722 fn parse_item_delegation(
723 &mut self,
724 attrs: &mut AttrVec,
725 defaultness: Defaultness,
726 kind: ReuseKind,
727 ) -> PResult<'a, ItemKind> {
728 let span = self.token.span;
729 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Reuse,
token_type: crate::parser::token_type::TokenType::KwReuse,
}exp!(Reuse))?;
730
731 let item_kind = match kind {
732 ReuseKind::Path => self.parse_path_like_delegation(),
733 ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
734 }?;
735
736 self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
737
738 Ok(item_kind)
739 }
740
741 fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
742 Ok(if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
743 Some(self.parse_block()?)
744 } else {
745 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))?;
746 None
747 })
748 }
749
750 fn parse_impl_delegation(
751 &mut self,
752 span: Span,
753 attrs: &mut AttrVec,
754 defaultness: Defaultness,
755 ) -> PResult<'a, ItemKind> {
756 let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
757 let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
758
759 let until_expr_span = span.to(self.prev_token.span);
760
761 let Some(of_trait) = of_trait else {
762 return Err(self
763 .dcx()
764 .create_err(errors::ImplReuseInherentImpl { span: until_expr_span }));
765 };
766
767 let body = self.parse_delegation_body()?;
768 let whole_reuse_span = span.to(self.prev_token.span);
769
770 items.push(Box::new(AssocItem {
771 id: DUMMY_NODE_ID,
772 attrs: Default::default(),
773 span: whole_reuse_span,
774 tokens: None,
775 vis: Visibility {
776 kind: VisibilityKind::Inherited,
777 span: whole_reuse_span,
778 tokens: None,
779 },
780 kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
781 qself: None,
782 prefix: of_trait.trait_ref.path.clone(),
783 suffixes: None,
784 body,
785 })),
786 }));
787
788 Ok(impl_item)
789 }
790
791 fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
792 let (qself, path) = if self.eat_lt() {
793 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
794 (Some(qself), path)
795 } else {
796 (None, self.parse_path(PathStyle::Expr)?)
797 };
798
799 let rename = |this: &mut Self| {
800 Ok(if this.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::As,
token_type: crate::parser::token_type::TokenType::KwAs,
}exp!(As)) { Some(this.parse_ident()?) } else { None })
801 };
802
803 Ok(if self.eat_path_sep() {
804 let suffixes = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
805 None
806 } else {
807 let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
808 Some(self.parse_delim_comma_seq(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), parse_suffix)?.0)
809 };
810
811 ItemKind::DelegationMac(Box::new(DelegationMac {
812 qself,
813 prefix: path,
814 suffixes,
815 body: self.parse_delegation_body()?,
816 }))
817 } else {
818 let rename = rename(self)?;
819 let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
820
821 ItemKind::Delegation(Box::new(Delegation {
822 id: DUMMY_NODE_ID,
823 qself,
824 path,
825 ident,
826 rename,
827 body: self.parse_delegation_body()?,
828 from_glob: false,
829 }))
830 })
831 }
832
833 fn parse_item_list<T>(
834 &mut self,
835 attrs: &mut AttrVec,
836 mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
837 ) -> PResult<'a, ThinVec<T>> {
838 let open_brace_span = self.token.span;
839
840 if self.token == TokenKind::Semi {
842 self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
843 self.bump();
844 return Ok(ThinVec::new());
845 }
846
847 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
848 attrs.extend(self.parse_inner_attributes()?);
849
850 let mut items = ThinVec::new();
851 while !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)) {
852 if self.recover_doc_comment_before_brace() {
853 continue;
854 }
855 self.recover_vcs_conflict_marker();
856 match parse_item(self) {
857 Ok(None) => {
858 let mut is_unnecessary_semicolon = !items.is_empty()
859 && self
877 .span_to_snippet(self.prev_token.span)
878 .is_ok_and(|snippet| snippet == "}")
879 && self.token == token::Semi;
880 let mut semicolon_span = self.token.span;
881 if !is_unnecessary_semicolon {
882 is_unnecessary_semicolon =
884 self.token == token::OpenBrace && self.prev_token == token::Semi;
885 semicolon_span = self.prev_token.span;
886 }
887 let non_item_span = self.token.span;
889 let is_let = self.token.is_keyword(kw::Let);
890
891 let mut err =
892 self.dcx().struct_span_err(non_item_span, "non-item in item list");
893 self.consume_block(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), ConsumeClosingDelim::Yes);
894 if is_let {
895 err.span_suggestion_verbose(
896 non_item_span,
897 "consider using `const` instead of `let` for associated const",
898 "const",
899 Applicability::MachineApplicable,
900 );
901 } else {
902 err.span_label(open_brace_span, "item list starts here")
903 .span_label(non_item_span, "non-item starts here")
904 .span_label(self.prev_token.span, "item list ends here");
905 }
906 if is_unnecessary_semicolon {
907 err.span_suggestion(
908 semicolon_span,
909 "consider removing this semicolon",
910 "",
911 Applicability::MaybeIncorrect,
912 );
913 }
914 err.emit();
915 break;
916 }
917 Ok(Some(item)) => items.extend(item),
918 Err(err) => {
919 self.consume_block(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), ConsumeClosingDelim::Yes);
920 err.with_span_label(
921 open_brace_span,
922 "while parsing this item list starting here",
923 )
924 .with_span_label(self.prev_token.span, "the item list ends here")
925 .emit();
926 break;
927 }
928 }
929 }
930 Ok(items)
931 }
932
933 fn recover_doc_comment_before_brace(&mut self) -> bool {
935 if let token::DocComment(..) = self.token.kind {
936 if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
937 {
self.dcx().struct_span_err(self.token.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("found a documentation comment that doesn\'t document anything"))
})).with_code(E0584)
}struct_span_code_err!(
939 self.dcx(),
940 self.token.span,
941 E0584,
942 "found a documentation comment that doesn't document anything",
943 )
944 .with_span_label(self.token.span, "this doc comment doesn't document anything")
945 .with_help(
946 "doc comments must come before what they document, if a comment was \
947 intended use `//`",
948 )
949 .emit();
950 self.bump();
951 return true;
952 }
953 }
954 false
955 }
956
957 fn parse_defaultness(&mut self) -> Defaultness {
959 if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Default,
token_type: crate::parser::token_type::TokenType::KwDefault,
}exp!(Default))
963 && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
964 {
965 self.bump(); Defaultness::Default(self.prev_token_uninterpolated_span())
967 } else {
968 Defaultness::Final
969 }
970 }
971
972 fn check_trait_front_matter(&mut self) -> bool {
974 self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Auto,
token_type: crate::parser::token_type::TokenType::KwAuto,
}exp!(Auto)) && self.is_keyword_ahead(1, &[kw::Trait])
976 || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe)) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto])
978 || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) && ((self.is_keyword_ahead(1, &[kw::Trait]) || self.is_keyword_ahead(1, &[kw::Auto]) && self.is_keyword_ahead(2, &[kw::Trait]))
979 || self.is_keyword_ahead(1, &[kw::Unsafe]) && self.is_keyword_ahead(2, &[kw::Trait, kw::Auto]))
980 }
981
982 fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
984 let constness = self.parse_constness(Case::Sensitive);
985 if let Const::Yes(span) = constness {
986 self.psess.gated_spans.gate(sym::const_trait_impl, span);
987 }
988 let safety = self.parse_safety(Case::Sensitive);
989 let is_auto = if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Auto,
token_type: crate::parser::token_type::TokenType::KwAuto,
}exp!(Auto)) {
991 self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
992 IsAuto::Yes
993 } else {
994 IsAuto::No
995 };
996
997 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait))?;
998 let ident = self.parse_ident()?;
999 let mut generics = self.parse_generics()?;
1000
1001 let had_colon = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon));
1003 let span_at_colon = self.prev_token.span;
1004 let bounds = if had_colon { self.parse_generic_bounds()? } else { Vec::new() };
1005
1006 let span_before_eq = self.prev_token.span;
1007 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1008 if had_colon {
1010 let span = span_at_colon.to(span_before_eq);
1011 self.dcx().emit_err(errors::BoundsNotAllowedOnTraitAliases { span });
1012 }
1013
1014 let bounds = self.parse_generic_bounds()?;
1015 generics.where_clause = self.parse_where_clause()?;
1016 self.expect_semi()?;
1017
1018 let whole_span = lo.to(self.prev_token.span);
1019 if is_auto == IsAuto::Yes {
1020 self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span });
1021 }
1022 if let Safety::Unsafe(_) = safety {
1023 self.dcx().emit_err(errors::TraitAliasCannotBeUnsafe { span: whole_span });
1024 }
1025
1026 self.psess.gated_spans.gate(sym::trait_alias, whole_span);
1027
1028 Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
1029 } else {
1030 generics.where_clause = self.parse_where_clause()?;
1032 let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
1033 Ok(ItemKind::Trait(Box::new(Trait {
1034 constness,
1035 is_auto,
1036 safety,
1037 ident,
1038 generics,
1039 bounds,
1040 items,
1041 })))
1042 }
1043 }
1044
1045 pub fn parse_impl_item(
1046 &mut self,
1047 force_collect: ForceCollect,
1048 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1049 let fn_parse_mode =
1050 FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
1051 self.parse_assoc_item(fn_parse_mode, force_collect)
1052 }
1053
1054 pub fn parse_trait_item(
1055 &mut self,
1056 force_collect: ForceCollect,
1057 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1058 let fn_parse_mode = FnParseMode {
1059 req_name: |edition, _| edition >= Edition::Edition2018,
1060 context: FnContext::Trait,
1061 req_body: false,
1062 };
1063 self.parse_assoc_item(fn_parse_mode, force_collect)
1064 }
1065
1066 fn parse_assoc_item(
1068 &mut self,
1069 fn_parse_mode: FnParseMode,
1070 force_collect: ForceCollect,
1071 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1072 Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
1073 |Item { attrs, id, span, vis, kind, tokens }| {
1074 let kind = match AssocItemKind::try_from(kind) {
1075 Ok(kind) => kind,
1076 Err(kind) => match kind {
1077 ItemKind::Static(box StaticItem {
1078 ident,
1079 ty,
1080 safety: _,
1081 mutability: _,
1082 expr,
1083 define_opaque,
1084 }) => {
1085 self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
1086 let rhs = expr.map(ConstItemRhs::Body);
1087 AssocItemKind::Const(Box::new(ConstItem {
1088 defaultness: Defaultness::Final,
1089 ident,
1090 generics: Generics::default(),
1091 ty,
1092 rhs,
1093 define_opaque,
1094 }))
1095 }
1096 _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
1097 },
1098 };
1099 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1100 },
1101 ))
1102 }
1103
1104 fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
1110 let ident = self.parse_ident()?;
1111 let mut generics = self.parse_generics()?;
1112
1113 let bounds = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) { self.parse_generic_bounds()? } else { Vec::new() };
1115 generics.where_clause = self.parse_where_clause()?;
1116
1117 let ty = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) { Some(self.parse_ty()?) } else { None };
1118
1119 let after_where_clause = self.parse_where_clause()?;
1120
1121 self.expect_semi()?;
1122
1123 Ok(ItemKind::TyAlias(Box::new(TyAlias {
1124 defaultness,
1125 ident,
1126 generics,
1127 after_where_clause,
1128 bounds,
1129 ty,
1130 })))
1131 }
1132
1133 fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
1143 let lo = self.token.span;
1144
1145 let mut prefix =
1146 ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo(), tokens: None };
1147 let kind =
1148 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) || self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) || self.is_import_coupler() {
1149 let mod_sep_ctxt = self.token.span.ctxt();
1151 if self.eat_path_sep() {
1152 prefix
1153 .segments
1154 .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
1155 }
1156
1157 self.parse_use_tree_glob_or_nested()?
1158 } else {
1159 prefix = self.parse_path(PathStyle::Mod)?;
1161
1162 if self.eat_path_sep() {
1163 self.parse_use_tree_glob_or_nested()?
1164 } else {
1165 while self.eat_noexpect(&token::Colon) {
1167 self.dcx()
1168 .emit_err(errors::SingleColonImportPath { span: self.prev_token.span });
1169
1170 self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
1172 prefix.span = lo.to(self.prev_token.span);
1173 }
1174
1175 UseTreeKind::Simple(self.parse_rename()?)
1176 }
1177 };
1178
1179 Ok(UseTree { prefix, kind, span: lo.to(self.prev_token.span) })
1180 }
1181
1182 fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
1184 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
1185 UseTreeKind::Glob
1186 } else {
1187 let lo = self.token.span;
1188 UseTreeKind::Nested {
1189 items: self.parse_use_tree_list()?,
1190 span: lo.to(self.prev_token.span),
1191 }
1192 })
1193 }
1194
1195 fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
1201 self.parse_delim_comma_seq(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), |p| {
1202 p.recover_vcs_conflict_marker();
1203 Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
1204 })
1205 .map(|(r, _)| r)
1206 }
1207
1208 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1209 if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::As,
token_type: crate::parser::token_type::TokenType::KwAs,
}exp!(As)) {
1210 self.parse_ident_or_underscore().map(Some)
1211 } else {
1212 Ok(None)
1213 }
1214 }
1215
1216 fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
1217 match self.token.ident() {
1218 Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
1219 self.bump();
1220 Ok(ident)
1221 }
1222 _ => self.parse_ident(),
1223 }
1224 }
1225
1226 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1235 let orig_ident = self.parse_crate_name_with_dashes()?;
1237 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1238 (Some(orig_ident.name), rename)
1239 } else {
1240 (None, orig_ident)
1241 };
1242 self.expect_semi()?;
1243 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1244 }
1245
1246 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1247 let ident = if self.token.is_keyword(kw::SelfLower) {
1248 self.parse_path_segment_ident()
1249 } else {
1250 self.parse_ident()
1251 }?;
1252
1253 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1254 if self.token != dash.tok {
1255 return Ok(ident);
1256 }
1257
1258 let mut dashes = ::alloc::vec::Vec::new()vec![];
1260 let mut idents = ::alloc::vec::Vec::new()vec![];
1261 while self.eat(dash) {
1262 dashes.push(self.prev_token.span);
1263 idents.push(self.parse_ident()?);
1264 }
1265
1266 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1267 let mut fixed_name = ident.name.to_string();
1268 for part in idents {
1269 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1270 }
1271
1272 self.dcx().emit_err(errors::ExternCrateNameWithDashes {
1273 span: fixed_name_sp,
1274 sugg: errors::ExternCrateNameWithDashesSugg { dashes },
1275 });
1276
1277 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1278 }
1279
1280 fn parse_item_foreign_mod(
1291 &mut self,
1292 attrs: &mut AttrVec,
1293 mut safety: Safety,
1294 ) -> PResult<'a, ItemKind> {
1295 let extern_span = self.prev_token_uninterpolated_span();
1296 let abi = self.parse_abi(); if safety == Safety::Default
1299 && self.token.is_keyword(kw::Unsafe)
1300 && self.look_ahead(1, |t| *t == token::OpenBrace)
1301 {
1302 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)).unwrap_err().emit();
1303 safety = Safety::Unsafe(self.token.span);
1304 let _ = self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe));
1305 }
1306 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1307 extern_span,
1308 safety,
1309 abi,
1310 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1311 }))
1312 }
1313
1314 pub fn parse_foreign_item(
1316 &mut self,
1317 force_collect: ForceCollect,
1318 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1319 let fn_parse_mode = FnParseMode {
1320 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1321 context: FnContext::Free,
1322 req_body: false,
1323 };
1324 Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
1325 |Item { attrs, id, span, vis, kind, tokens }| {
1326 let kind = match ForeignItemKind::try_from(kind) {
1327 Ok(kind) => kind,
1328 Err(kind) => match kind {
1329 ItemKind::Const(box ConstItem { ident, ty, rhs, .. }) => {
1330 let const_span = Some(span.with_hi(ident.span.lo()))
1331 .filter(|span| span.can_be_used_for_suggestions());
1332 self.dcx().emit_err(errors::ExternItemCannotBeConst {
1333 ident_span: ident.span,
1334 const_span,
1335 });
1336 ForeignItemKind::Static(Box::new(StaticItem {
1337 ident,
1338 ty,
1339 mutability: Mutability::Not,
1340 expr: rhs.map(|b| match b {
1341 ConstItemRhs::TypeConst(anon_const) => anon_const.value,
1342 ConstItemRhs::Body(expr) => expr,
1343 }),
1344 safety: Safety::Default,
1345 define_opaque: None,
1346 }))
1347 }
1348 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1349 },
1350 };
1351 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1352 },
1353 ))
1354 }
1355
1356 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1357 let span = self.psess.source_map().guess_head_span(span);
1359 let descr = kind.descr();
1360 let help = match kind {
1361 ItemKind::DelegationMac(deleg) if deleg.suffixes.is_none() => false,
1362 _ => true,
1363 };
1364 self.dcx().emit_err(errors::BadItemKind { span, descr, ctx, help });
1365 None
1366 }
1367
1368 fn is_use_closure(&self) -> bool {
1369 if self.token.is_keyword(kw::Use) {
1370 self.look_ahead(1, |token| {
1372 let dist =
1374 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1375
1376 self.look_ahead(dist, |token| #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr))
1377 })
1378 } else {
1379 false
1380 }
1381 }
1382
1383 fn is_unsafe_foreign_mod(&self) -> bool {
1384 if !self.token.is_keyword(kw::Unsafe) {
1386 return false;
1387 }
1388 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1390 return false;
1391 }
1392
1393 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1395
1396 self.tree_look_ahead(n, |t| #[allow(non_exhaustive_omitted_patterns)] match t {
TokenTree::Delimited(_, _, Delimiter::Brace, _) => true,
_ => false,
}matches!(t, TokenTree::Delimited(_, _, Delimiter::Brace, _)))
1401 == Some(true)
1402 }
1403
1404 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1405 let is_global_static = if self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Static,
token_type: crate::parser::token_type::TokenType::KwStatic,
}exp!(Static), case) {
1406 !self.look_ahead(1, |token| {
1408 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1409 return true;
1410 }
1411 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1412 })
1413 } else {
1414 (self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe), case)
1416 || self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe), case))
1417 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1418 };
1419
1420 if is_global_static {
1421 let safety = self.parse_safety(case);
1422 let _ = self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Static,
token_type: crate::parser::token_type::TokenType::KwStatic,
}exp!(Static), case);
1423 Some(safety)
1424 } else {
1425 None
1426 }
1427 }
1428
1429 fn recover_const_mut(&mut self, const_span: Span) {
1431 if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mut,
token_type: crate::parser::token_type::TokenType::KwMut,
}exp!(Mut)) {
1432 let span = self.prev_token.span;
1433 self.dcx()
1434 .emit_err(errors::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1435 } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Let,
token_type: crate::parser::token_type::TokenType::KwLet,
}exp!(Let)) {
1436 let span = self.prev_token.span;
1437 self.dcx().emit_err(errors::ConstLetMutuallyExclusive { span: const_span.to(span) });
1438 }
1439 }
1440
1441 fn parse_static_item(
1448 &mut self,
1449 safety: Safety,
1450 mutability: Mutability,
1451 ) -> PResult<'a, ItemKind> {
1452 let ident = self.parse_ident()?;
1453
1454 if self.token == TokenKind::Lt && self.may_recover() {
1455 let generics = self.parse_generics()?;
1456 self.dcx().emit_err(errors::StaticWithGenerics { span: generics.span });
1457 }
1458
1459 let ty = match (self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)), self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) | self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))) {
1462 (true, false) => self.parse_ty()?,
1463 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1466 };
1467
1468 let expr = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) { Some(self.parse_expr()?) } else { None };
1469
1470 self.expect_semi()?;
1471
1472 let item = StaticItem { ident, ty, safety, mutability, expr, define_opaque: None };
1473 Ok(ItemKind::Static(Box::new(item)))
1474 }
1475
1476 fn parse_const_item(
1482 &mut self,
1483 attrs: &[Attribute],
1484 ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<ast::ConstItemRhs>)> {
1485 let ident = self.parse_ident_or_underscore()?;
1486
1487 let mut generics = self.parse_generics()?;
1488
1489 if !generics.span.is_empty() {
1492 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1493 }
1494
1495 let ty = match (
1498 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1499 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) | self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) | self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Where,
token_type: crate::parser::token_type::TokenType::KwWhere,
}exp!(Where)),
1500 ) {
1501 (true, false) => self.parse_ty()?,
1502 (colon, _) => self.recover_missing_global_item_type(colon, None),
1504 };
1505
1506 let before_where_clause =
1509 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1510
1511 let rhs = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1512 if attr::contains_name(attrs, sym::type_const) {
1513 Some(ConstItemRhs::TypeConst(self.parse_const_arg()?))
1514 } else {
1515 Some(ConstItemRhs::Body(self.parse_expr()?))
1516 }
1517 } else {
1518 None
1519 };
1520
1521 let after_where_clause = self.parse_where_clause()?;
1522
1523 if before_where_clause.has_where_token
1527 && let Some(rhs) = &rhs
1528 {
1529 self.dcx().emit_err(errors::WhereClauseBeforeConstBody {
1530 span: before_where_clause.span,
1531 name: ident.span,
1532 body: rhs.span(),
1533 sugg: if !after_where_clause.has_where_token {
1534 self.psess.source_map().span_to_snippet(rhs.span()).ok().map(|body_s| {
1535 errors::WhereClauseBeforeConstBodySugg {
1536 left: before_where_clause.span.shrink_to_lo(),
1537 snippet: body_s,
1538 right: before_where_clause.span.shrink_to_hi().to(rhs.span()),
1539 }
1540 })
1541 } else {
1542 None
1545 },
1546 });
1547 }
1548
1549 let mut predicates = before_where_clause.predicates;
1556 predicates.extend(after_where_clause.predicates);
1557 let where_clause = WhereClause {
1558 has_where_token: before_where_clause.has_where_token
1559 || after_where_clause.has_where_token,
1560 predicates,
1561 span: if after_where_clause.has_where_token {
1562 after_where_clause.span
1563 } else {
1564 before_where_clause.span
1565 },
1566 };
1567
1568 if where_clause.has_where_token {
1569 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1570 }
1571
1572 generics.where_clause = where_clause;
1573
1574 self.expect_semi()?;
1575
1576 Ok((ident, generics, ty, rhs))
1577 }
1578
1579 fn recover_missing_global_item_type(
1582 &mut self,
1583 colon_present: bool,
1584 m: Option<Mutability>,
1585 ) -> Box<Ty> {
1586 let kind = match m {
1589 Some(Mutability::Mut) => "static mut",
1590 Some(Mutability::Not) => "static",
1591 None => "const",
1592 };
1593
1594 let colon = match colon_present {
1595 true => "",
1596 false => ":",
1597 };
1598
1599 let span = self.prev_token.span.shrink_to_hi();
1600 let err = self.dcx().create_err(errors::MissingConstType { span, colon, kind });
1601 err.stash(span, StashKey::ItemNoType);
1602
1603 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None })
1606 }
1607
1608 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1610 if self.token.is_keyword(kw::Struct) {
1611 let span = self.prev_token.span.to(self.token.span);
1612 let err = errors::EnumStructMutuallyExclusive { span };
1613 if self.look_ahead(1, |t| t.is_ident()) {
1614 self.bump();
1615 self.dcx().emit_err(err);
1616 } else {
1617 return Err(self.dcx().create_err(err));
1618 }
1619 }
1620
1621 let prev_span = self.prev_token.span;
1622 let ident = self.parse_ident()?;
1623 let mut generics = self.parse_generics()?;
1624 generics.where_clause = self.parse_where_clause()?;
1625
1626 let (variants, _) = if self.token == TokenKind::Semi {
1628 self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
1629 self.bump();
1630 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1631 } else {
1632 self.parse_delim_comma_seq(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), |p| {
1633 p.parse_enum_variant(ident.span)
1634 })
1635 .map_err(|mut err| {
1636 err.span_label(ident.span, "while parsing this enum");
1637 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1639 let snapshot = self.create_snapshot_for_diagnostic();
1640 self.bump();
1641 match self.parse_ty() {
1642 Ok(_) => {
1643 err.span_suggestion_verbose(
1644 prev_span,
1645 "perhaps you meant to use `struct` here",
1646 "struct",
1647 Applicability::MaybeIncorrect,
1648 );
1649 }
1650 Err(e) => {
1651 e.cancel();
1652 }
1653 }
1654 self.restore_snapshot(snapshot);
1655 }
1656 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1657 self.bump(); err
1659 })?
1660 };
1661
1662 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1663 Ok(ItemKind::Enum(ident, generics, enum_definition))
1664 }
1665
1666 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1667 self.recover_vcs_conflict_marker();
1668 let variant_attrs = self.parse_outer_attributes()?;
1669 self.recover_vcs_conflict_marker();
1670 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1671 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1672 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1673 let vlo = this.token.span;
1674
1675 let vis = this.parse_visibility(FollowedByType::No)?;
1676 if !this.recover_nested_adt_item(kw::Enum)? {
1677 return Ok((None, Trailing::No, UsePreAttrPos::No));
1678 }
1679 let ident = this.parse_field_ident("enum", vlo)?;
1680
1681 if this.token == token::Bang {
1682 if let Err(err) = this.unexpected() {
1683 err.with_note(fluent::parse_macro_expands_to_enum_variant).emit();
1684 }
1685
1686 this.bump();
1687 this.parse_delim_args()?;
1688
1689 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1690 }
1691
1692 let struct_def = if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
1693 let (fields, recovered) =
1695 match this.parse_record_struct_body("struct", ident.span, false) {
1696 Ok((fields, recovered)) => (fields, recovered),
1697 Err(mut err) => {
1698 if this.token == token::Colon {
1699 return Err(err);
1701 }
1702 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1703 this.bump(); err.span_label(span, "while parsing this enum");
1705 err.help(help);
1706 let guar = err.emit();
1707 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1708 }
1709 };
1710 VariantData::Struct { fields, recovered }
1711 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1712 let body = match this.parse_tuple_struct_body() {
1713 Ok(body) => body,
1714 Err(mut err) => {
1715 if this.token == token::Colon {
1716 return Err(err);
1718 }
1719 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
1720 this.bump(); err.span_label(span, "while parsing this enum");
1722 err.help(help);
1723 err.emit();
1724 ::thin_vec::ThinVec::new()thin_vec![]
1725 }
1726 };
1727 VariantData::Tuple(body, DUMMY_NODE_ID)
1728 } else {
1729 VariantData::Unit(DUMMY_NODE_ID)
1730 };
1731
1732 let disr_expr = if this.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1733 Some(this.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?)
1734 } else {
1735 None
1736 };
1737
1738 let vr = ast::Variant {
1739 ident,
1740 vis,
1741 id: DUMMY_NODE_ID,
1742 attrs: variant_attrs,
1743 data: struct_def,
1744 disr_expr,
1745 span: vlo.to(this.prev_token.span),
1746 is_placeholder: false,
1747 };
1748
1749 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
1750 })
1751 .map_err(|mut err| {
1752 err.help(help);
1753 err
1754 })
1755 }
1756
1757 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
1759 let ident = self.parse_ident()?;
1760
1761 let mut generics = self.parse_generics()?;
1762
1763 let vdata = if self.token.is_keyword(kw::Where) {
1778 let tuple_struct_body;
1779 (generics.where_clause, tuple_struct_body) =
1780 self.parse_struct_where_clause(ident, generics.span)?;
1781
1782 if let Some(body) = tuple_struct_body {
1783 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
1785 self.expect_semi()?;
1786 body
1787 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1788 VariantData::Unit(DUMMY_NODE_ID)
1790 } else {
1791 let (fields, recovered) = self.parse_record_struct_body(
1793 "struct",
1794 ident.span,
1795 generics.where_clause.has_where_token,
1796 )?;
1797 VariantData::Struct { fields, recovered }
1798 }
1799 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1801 VariantData::Unit(DUMMY_NODE_ID)
1802 } else if self.token == token::OpenBrace {
1804 let (fields, recovered) = self.parse_record_struct_body(
1805 "struct",
1806 ident.span,
1807 generics.where_clause.has_where_token,
1808 )?;
1809 VariantData::Struct { fields, recovered }
1810 } else if self.token == token::OpenParen {
1812 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
1813 generics.where_clause = self.parse_where_clause()?;
1814 self.expect_semi()?;
1815 body
1816 } else {
1817 let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
1818 return Err(self.dcx().create_err(err));
1819 };
1820
1821 Ok(ItemKind::Struct(ident, generics, vdata))
1822 }
1823
1824 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
1826 let ident = self.parse_ident()?;
1827
1828 let mut generics = self.parse_generics()?;
1829
1830 let vdata = if self.token.is_keyword(kw::Where) {
1831 generics.where_clause = self.parse_where_clause()?;
1832 let (fields, recovered) = self.parse_record_struct_body(
1833 "union",
1834 ident.span,
1835 generics.where_clause.has_where_token,
1836 )?;
1837 VariantData::Struct { fields, recovered }
1838 } else if self.token == token::OpenBrace {
1839 let (fields, recovered) = self.parse_record_struct_body(
1840 "union",
1841 ident.span,
1842 generics.where_clause.has_where_token,
1843 )?;
1844 VariantData::Struct { fields, recovered }
1845 } else {
1846 let token_str = super::token_descr(&self.token);
1847 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected `where` or `{{` after union name, found {0}",
token_str))
})format!("expected `where` or `{{` after union name, found {token_str}");
1848 let mut err = self.dcx().struct_span_err(self.token.span, msg);
1849 err.span_label(self.token.span, "expected `where` or `{` after union name");
1850 return Err(err);
1851 };
1852
1853 Ok(ItemKind::Union(ident, generics, vdata))
1854 }
1855
1856 pub(crate) fn parse_record_struct_body(
1861 &mut self,
1862 adt_ty: &str,
1863 ident_span: Span,
1864 parsed_where: bool,
1865 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
1866 let mut fields = ThinVec::new();
1867 let mut recovered = Recovered::No;
1868 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
1869 while self.token != token::CloseBrace {
1870 match self.parse_field_def(adt_ty, ident_span) {
1871 Ok(field) => {
1872 fields.push(field);
1873 }
1874 Err(mut err) => {
1875 self.consume_block(
1876 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
1877 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
1878 ConsumeClosingDelim::No,
1879 );
1880 err.span_label(ident_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("while parsing this {0}", adt_ty))
})format!("while parsing this {adt_ty}"));
1881 let guar = err.emit();
1882 recovered = Recovered::Yes(guar);
1883 break;
1884 }
1885 }
1886 }
1887 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
1888 } else {
1889 let token_str = super::token_descr(&self.token);
1890 let where_str = if parsed_where { "" } else { "`where`, or " };
1891 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}`{{` after struct name, found {1}",
where_str, token_str))
})format!("expected {where_str}`{{` after struct name, found {token_str}");
1892 let mut err = self.dcx().struct_span_err(self.token.span, msg);
1893 err.span_label(self.token.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}`{{` after struct name",
where_str))
})format!("expected {where_str}`{{` after struct name",));
1894 return Err(err);
1895 }
1896
1897 Ok((fields, recovered))
1898 }
1899
1900 fn parse_unsafe_field(&mut self) -> Safety {
1901 if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe)) {
1903 let span = self.prev_token.span;
1904 self.psess.gated_spans.gate(sym::unsafe_fields, span);
1905 Safety::Unsafe(span)
1906 } else {
1907 Safety::Default
1908 }
1909 }
1910
1911 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
1912 self.parse_paren_comma_seq(|p| {
1915 let attrs = p.parse_outer_attributes()?;
1916 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
1917 let mut snapshot = None;
1918 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
1919 snapshot = Some(p.create_snapshot_for_diagnostic());
1923 }
1924 let lo = p.token.span;
1925 let vis = match p.parse_visibility(FollowedByType::Yes) {
1926 Ok(vis) => vis,
1927 Err(err) => {
1928 if let Some(ref mut snapshot) = snapshot {
1929 snapshot.recover_vcs_conflict_marker();
1930 }
1931 return Err(err);
1932 }
1933 };
1934 let ty = match p.parse_ty() {
1937 Ok(ty) => ty,
1938 Err(err) => {
1939 if let Some(ref mut snapshot) = snapshot {
1940 snapshot.recover_vcs_conflict_marker();
1941 }
1942 return Err(err);
1943 }
1944 };
1945 let mut default = None;
1946 if p.token == token::Eq {
1947 let mut snapshot = p.create_snapshot_for_diagnostic();
1948 snapshot.bump();
1949 match snapshot.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst) {
1950 Ok(const_expr) => {
1951 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
1952 p.psess.gated_spans.gate(sym::default_field_values, sp);
1953 p.restore_snapshot(snapshot);
1954 default = Some(const_expr);
1955 }
1956 Err(err) => {
1957 err.cancel();
1958 }
1959 }
1960 }
1961
1962 Ok((
1963 FieldDef {
1964 span: lo.to(ty.span),
1965 vis,
1966 safety: Safety::Default,
1967 ident: None,
1968 id: DUMMY_NODE_ID,
1969 ty,
1970 default,
1971 attrs,
1972 is_placeholder: false,
1973 },
1974 Trailing::from(p.token == token::Comma),
1975 UsePreAttrPos::No,
1976 ))
1977 })
1978 })
1979 .map(|(r, _)| r)
1980 }
1981
1982 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
1984 self.recover_vcs_conflict_marker();
1985 let attrs = self.parse_outer_attributes()?;
1986 self.recover_vcs_conflict_marker();
1987 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
1988 let lo = this.token.span;
1989 let vis = this.parse_visibility(FollowedByType::No)?;
1990 let safety = this.parse_unsafe_field();
1991 this.parse_single_struct_field(adt_ty, lo, vis, safety, attrs, ident_span)
1992 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
1993 })
1994 }
1995
1996 fn parse_single_struct_field(
1998 &mut self,
1999 adt_ty: &str,
2000 lo: Span,
2001 vis: Visibility,
2002 safety: Safety,
2003 attrs: AttrVec,
2004 ident_span: Span,
2005 ) -> PResult<'a, FieldDef> {
2006 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, safety, attrs)?;
2007 match self.token.kind {
2008 token::Comma => {
2009 self.bump();
2010 }
2011 token::Semi => {
2012 self.bump();
2013 let sp = self.prev_token.span;
2014 let mut err =
2015 self.dcx().struct_span_err(sp, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} fields are separated by `,`",
adt_ty))
})format!("{adt_ty} fields are separated by `,`"));
2016 err.span_suggestion_short(
2017 sp,
2018 "replace `;` with `,`",
2019 ",",
2020 Applicability::MachineApplicable,
2021 );
2022 err.span_label(ident_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("while parsing this {0}", adt_ty))
})format!("while parsing this {adt_ty}"));
2023 err.emit();
2024 }
2025 token::CloseBrace => {}
2026 token::DocComment(..) => {
2027 let previous_span = self.prev_token.span;
2028 let mut err = errors::DocCommentDoesNotDocumentAnything {
2029 span: self.token.span,
2030 missing_comma: None,
2031 };
2032 self.bump(); if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma)) || self.token == token::CloseBrace {
2034 self.dcx().emit_err(err);
2035 } else {
2036 let sp = previous_span.shrink_to_hi();
2037 err.missing_comma = Some(sp);
2038 return Err(self.dcx().create_err(err));
2039 }
2040 }
2041 _ => {
2042 let sp = self.prev_token.span.shrink_to_hi();
2043 let msg =
2044 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected `,`, or `}}`, found {0}",
super::token_descr(&self.token)))
})format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token));
2045
2046 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2048 && let Some(last_segment) = segments.last()
2049 {
2050 let guar = self.check_trailing_angle_brackets(
2051 last_segment,
2052 &[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::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)],
2053 );
2054 if let Some(_guar) = guar {
2055 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2058
2059 return Ok(a_var);
2062 }
2063 }
2064
2065 let mut err = self.dcx().struct_span_err(sp, msg);
2066
2067 if self.token.is_ident()
2068 || (self.token == TokenKind::Pound
2069 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2070 {
2071 err.span_suggestion(
2074 sp,
2075 "try adding a comma",
2076 ",",
2077 Applicability::MachineApplicable,
2078 );
2079 err.emit();
2080 } else {
2081 return Err(err);
2082 }
2083 }
2084 }
2085 Ok(a_var)
2086 }
2087
2088 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2089 if let Err(err) = self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) {
2090 let sm = self.psess.source_map();
2091 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2092 let semi_typo = self.token == token::Semi
2093 && self.look_ahead(1, |t| {
2094 t.is_path_start()
2095 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2098 (Ok(l), Ok(r)) => l.line == r.line,
2099 _ => true,
2100 }
2101 });
2102 if eq_typo || semi_typo {
2103 self.bump();
2104 err.with_span_suggestion_short(
2106 self.prev_token.span,
2107 "field names and their types are separated with `:`",
2108 ":",
2109 Applicability::MachineApplicable,
2110 )
2111 .emit();
2112 } else {
2113 return Err(err);
2114 }
2115 }
2116 Ok(())
2117 }
2118
2119 fn parse_name_and_ty(
2121 &mut self,
2122 adt_ty: &str,
2123 lo: Span,
2124 vis: Visibility,
2125 safety: Safety,
2126 attrs: AttrVec,
2127 ) -> PResult<'a, FieldDef> {
2128 let name = self.parse_field_ident(adt_ty, lo)?;
2129 if self.token == token::Bang {
2130 if let Err(mut err) = self.unexpected() {
2131 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2133 return Err(err);
2134 }
2135 }
2136 self.expect_field_ty_separator()?;
2137 let ty = self.parse_ty()?;
2138 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2139 self.dcx()
2140 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2141 .with_span_suggestion_verbose(
2142 self.token.span,
2143 "write a path separator here",
2144 "::",
2145 Applicability::MaybeIncorrect,
2146 )
2147 .emit();
2148 }
2149 let default = if self.token == token::Eq {
2150 self.bump();
2151 let const_expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
2152 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2153 self.psess.gated_spans.gate(sym::default_field_values, sp);
2154 Some(const_expr)
2155 } else {
2156 None
2157 };
2158 Ok(FieldDef {
2159 span: lo.to(self.prev_token.span),
2160 ident: Some(name),
2161 vis,
2162 safety,
2163 id: DUMMY_NODE_ID,
2164 ty,
2165 default,
2166 attrs,
2167 is_placeholder: false,
2168 })
2169 }
2170
2171 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2174 let (ident, is_raw) = self.ident_or_err(true)?;
2175 if is_raw == IdentIsRaw::No && ident.is_reserved() {
2176 let snapshot = self.create_snapshot_for_diagnostic();
2177 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2178 let inherited_vis =
2179 Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
2180 let fn_parse_mode =
2182 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2183 match self.parse_fn(
2184 &mut AttrVec::new(),
2185 fn_parse_mode,
2186 lo,
2187 &inherited_vis,
2188 Case::Insensitive,
2189 ) {
2190 Ok(_) => {
2191 self.dcx().struct_span_err(
2192 lo.to(self.prev_token.span),
2193 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("functions are not allowed in {0} definitions",
adt_ty))
})format!("functions are not allowed in {adt_ty} definitions"),
2194 )
2195 .with_help(
2196 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2197 )
2198 .with_help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information")
2199 }
2200 Err(err) => {
2201 err.cancel();
2202 self.restore_snapshot(snapshot);
2203 self.expected_ident_found_err()
2204 }
2205 }
2206 } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Struct,
token_type: crate::parser::token_type::TokenType::KwStruct,
}exp!(Struct)) {
2207 match self.parse_item_struct() {
2208 Ok(item) => {
2209 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2210 self.dcx()
2211 .struct_span_err(
2212 lo.with_hi(ident.span.hi()),
2213 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("structs are not allowed in {0} definitions",
adt_ty))
})format!("structs are not allowed in {adt_ty} definitions"),
2214 )
2215 .with_help(
2216 "consider creating a new `struct` definition instead of nesting",
2217 )
2218 }
2219 Err(err) => {
2220 err.cancel();
2221 self.restore_snapshot(snapshot);
2222 self.expected_ident_found_err()
2223 }
2224 }
2225 } else {
2226 let mut err = self.expected_ident_found_err();
2227 if self.eat_keyword_noexpect(kw::Let)
2228 && let removal_span = self.prev_token.span.until(self.token.span)
2229 && let Ok(ident) = self
2230 .parse_ident_common(false)
2231 .map_err(|err| err.cancel())
2233 && self.token == TokenKind::Colon
2234 {
2235 err.span_suggestion(
2236 removal_span,
2237 "remove this `let` keyword",
2238 String::new(),
2239 Applicability::MachineApplicable,
2240 );
2241 err.note("the `let` keyword is not allowed in `struct` fields");
2242 err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
2243 err.emit();
2244 return Ok(ident);
2245 } else {
2246 self.restore_snapshot(snapshot);
2247 }
2248 err
2249 };
2250 return Err(err);
2251 }
2252 self.bump();
2253 Ok(ident)
2254 }
2255
2256 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2264 let ident = self.parse_ident()?;
2265 let body = if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2266 self.parse_delim_args()? } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
2268 let params = self.parse_token_tree(); let pspan = params.span();
2270 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2271 self.unexpected()?;
2272 }
2273 let body = self.parse_token_tree(); let bspan = body.span();
2276 let arrow = TokenTree::token_alone(token::FatArrow, pspan.between(bspan)); let tokens = TokenStream::new(<[_]>::into_vec(::alloc::boxed::box_new([params, arrow, body]))vec![params, arrow, body]);
2278 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2279 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2280 } else {
2281 self.unexpected_any()?
2282 };
2283
2284 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2285 Ok(ItemKind::MacroDef(
2286 ident,
2287 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2288 ))
2289 }
2290
2291 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2293 if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::MacroRules,
token_type: crate::parser::token_type::TokenType::KwMacroRules,
}exp!(MacroRules)) {
2294 let macro_rules_span = self.token.span;
2295
2296 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2297 return IsMacroRulesItem::Yes { has_bang: true };
2298 } else if self.look_ahead(1, |t| t.is_ident()) {
2299 self.dcx().emit_err(errors::MacroRulesMissingBang {
2301 span: macro_rules_span,
2302 hi: macro_rules_span.shrink_to_hi(),
2303 });
2304
2305 return IsMacroRulesItem::Yes { has_bang: false };
2306 }
2307 }
2308
2309 IsMacroRulesItem::No
2310 }
2311
2312 fn parse_item_macro_rules(
2314 &mut self,
2315 vis: &Visibility,
2316 has_bang: bool,
2317 ) -> PResult<'a, ItemKind> {
2318 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::MacroRules,
token_type: crate::parser::token_type::TokenType::KwMacroRules,
}exp!(MacroRules))?; if has_bang {
2321 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2323 let ident = self.parse_ident()?;
2324
2325 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2326 let span = self.prev_token.span;
2328 self.dcx().emit_err(errors::MacroNameRemoveBang { span });
2329 }
2330
2331 let body = self.parse_delim_args()?;
2332 self.eat_semi_for_macro_if_needed(&body);
2333 self.complain_if_pub_macro(vis, true);
2334
2335 Ok(ItemKind::MacroDef(
2336 ident,
2337 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2338 ))
2339 }
2340
2341 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2344 if let VisibilityKind::Inherited = vis.kind {
2345 return;
2346 }
2347
2348 let vstr = pprust::vis_to_string(vis);
2349 let vstr = vstr.trim_end();
2350 if macro_rules {
2351 self.dcx().emit_err(errors::MacroRulesVisibility { span: vis.span, vis: vstr });
2352 } else {
2353 self.dcx().emit_err(errors::MacroInvocationVisibility { span: vis.span, vis: vstr });
2354 }
2355 }
2356
2357 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs) {
2358 if args.need_semicolon() && !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
2359 self.report_invalid_macro_expansion_item(args);
2360 }
2361 }
2362
2363 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs) {
2364 let span = args.dspan.entire();
2365 let mut err = self.dcx().struct_span_err(
2366 span,
2367 "macros that expand to items must be delimited with braces or followed by a semicolon",
2368 );
2369 if !span.from_expansion() {
2372 let DelimSpan { open, close } = args.dspan;
2373 err.multipart_suggestion(
2374 "change the delimiters to curly braces",
2375 <[_]>::into_vec(::alloc::boxed::box_new([(open, "{".to_string()),
(close, '}'.to_string())]))vec![(open, "{".to_string()), (close, '}'.to_string())],
2376 Applicability::MaybeIncorrect,
2377 );
2378 err.span_suggestion(
2379 span.with_neighbor(self.token.span).shrink_to_hi(),
2380 "add a semicolon",
2381 ';',
2382 Applicability::MaybeIncorrect,
2383 );
2384 }
2385 err.emit();
2386 }
2387
2388 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2391 if (self.token.is_keyword(kw::Enum)
2392 || self.token.is_keyword(kw::Struct)
2393 || self.token.is_keyword(kw::Union))
2394 && self.look_ahead(1, |t| t.is_ident())
2395 {
2396 let kw_token = self.token;
2397 let kw_str = pprust::token_to_string(&kw_token);
2398 let item = self.parse_item(ForceCollect::No)?;
2399 let mut item = item.unwrap().span;
2400 if self.token == token::Comma {
2401 item = item.to(self.token.span);
2402 }
2403 self.dcx().emit_err(errors::NestedAdt {
2404 span: kw_token.span,
2405 item,
2406 kw_str,
2407 keyword: keyword.as_str(),
2408 });
2409 return Ok(false);
2411 }
2412 Ok(true)
2413 }
2414}
2415
2416type ReqName = fn(Edition, IsDotDotDot) -> bool;
2425
2426#[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)]
2427pub(crate) enum IsDotDotDot {
2428 Yes,
2429 No,
2430}
2431
2432#[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)]
2440pub(crate) struct FnParseMode {
2441 pub(super) req_name: ReqName,
2467 pub(super) context: FnContext,
2470 pub(super) req_body: bool,
2489}
2490
2491#[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_receiver_is_total_eq(&self) -> () {}
}Eq)]
2494pub(crate) enum FnContext {
2495 Free,
2497 Trait,
2499 Impl,
2501}
2502
2503impl<'a> Parser<'a> {
2505 fn parse_fn(
2507 &mut self,
2508 attrs: &mut AttrVec,
2509 fn_parse_mode: FnParseMode,
2510 sig_lo: Span,
2511 vis: &Visibility,
2512 case: Case,
2513 ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
2514 let fn_span = self.token.span;
2515 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)
2519 {
2520 Ok(decl) => decl,
2521 Err(old_err) => {
2522 if self.token.is_keyword(kw::For) {
2524 old_err.cancel();
2525 return Err(self.dcx().create_err(errors::FnTypoWithImpl { fn_span }));
2526 } else {
2527 return Err(old_err);
2528 }
2529 }
2530 };
2531
2532 let fn_params_end = self.prev_token.span.shrink_to_hi();
2535
2536 let contract = self.parse_contract()?;
2537
2538 generics.where_clause = self.parse_where_clause()?; let fn_params_end =
2542 if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
2543
2544 let mut sig_hi = self.prev_token.span;
2545 let body =
2547 self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
2548 let fn_sig_span = sig_lo.to(sig_hi);
2549 Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
2550 }
2551
2552 fn error_fn_body_not_found(
2554 &mut self,
2555 ident_span: Span,
2556 req_body: bool,
2557 fn_params_end: Option<Span>,
2558 ) -> PResult<'a, ErrorGuaranteed> {
2559 let expected: &[_] =
2560 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)] };
2561 match self.expected_one_of_not_found(&[], expected) {
2562 Ok(error_guaranteed) => Ok(error_guaranteed),
2563 Err(mut err) => {
2564 if self.token == token::CloseBrace {
2565 err.span_label(ident_span, "while parsing this `fn`");
2568 Ok(err.emit())
2569 } else if self.token == token::RArrow
2570 && let Some(fn_params_end) = fn_params_end
2571 {
2572 let fn_trait_span =
2578 [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
2579 if self.prev_token.is_ident_named(symbol) {
2580 Some(self.prev_token.span)
2581 } else {
2582 None
2583 }
2584 });
2585
2586 let arrow_span = self.token.span;
2591 let ty_span = match self.parse_ret_ty(
2592 AllowPlus::Yes,
2593 RecoverQPath::Yes,
2594 RecoverReturnSign::Yes,
2595 ) {
2596 Ok(ty_span) => ty_span.span().shrink_to_hi(),
2597 Err(parse_error) => {
2598 parse_error.cancel();
2599 return Err(err);
2600 }
2601 };
2602 let ret_ty_span = arrow_span.to(ty_span);
2603
2604 if let Some(fn_trait_span) = fn_trait_span {
2605 err.subdiagnostic(errors::FnTraitMissingParen { span: fn_trait_span });
2608 } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
2609 {
2610 err.primary_message(
2614 "return type should be specified after the function parameters",
2615 );
2616 err.subdiagnostic(errors::MisplacedReturnType {
2617 fn_params_end,
2618 snippet,
2619 ret_ty_span,
2620 });
2621 }
2622 Err(err)
2623 } else {
2624 Err(err)
2625 }
2626 }
2627 }
2628 }
2629
2630 fn parse_fn_body(
2634 &mut self,
2635 attrs: &mut AttrVec,
2636 ident: &Ident,
2637 sig_hi: &mut Span,
2638 req_body: bool,
2639 fn_params_end: Option<Span>,
2640 ) -> PResult<'a, Option<Box<Block>>> {
2641 let has_semi = if req_body {
2642 self.token == TokenKind::Semi
2643 } else {
2644 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))
2646 };
2647 let (inner_attrs, body) = if has_semi {
2648 self.expect_semi()?;
2650 *sig_hi = self.prev_token.span;
2651 (AttrVec::new(), None)
2652 } 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() {
2653 self.parse_block_common(self.token.span, BlockCheckMode::Default, None)
2654 .map(|(attrs, body)| (attrs, Some(body)))?
2655 } else if self.token == token::Eq {
2656 self.bump(); let eq_sp = self.prev_token.span;
2659 let _ = self.parse_expr()?;
2660 self.expect_semi()?; let span = eq_sp.to(self.prev_token.span);
2662 let guar = self.dcx().emit_err(errors::FunctionBodyEqualsExpr {
2663 span,
2664 sugg: errors::FunctionBodyEqualsExprSugg { eq: eq_sp, semi: self.prev_token.span },
2665 });
2666 (AttrVec::new(), Some(self.mk_block_err(span, guar)))
2667 } else {
2668 self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
2669 (AttrVec::new(), None)
2670 };
2671 attrs.extend(inner_attrs);
2672 Ok(body)
2673 }
2674
2675 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2676 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2677 if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl)) {
2680 return true;
2681 }
2682 let mut i = 0;
2683 while i < ALL_QUALS.len() {
2684 let action = self.look_ahead(i + look_ahead, |token| {
2685 if token.is_keyword(kw::Impl) {
2686 return Some(true);
2687 }
2688 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2689 return None;
2691 }
2692 Some(false)
2693 });
2694 if let Some(ret) = action {
2695 return ret;
2696 }
2697 i += 1;
2698 }
2699
2700 self.is_keyword_ahead(i, &[kw::Impl])
2701 }
2702
2703 pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
2708 const ALL_QUALS: &[ExpKeywordPair] = &[
2709 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub),
2710 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen),
2711 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const),
2712 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async),
2713 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe),
2714 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe),
2715 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern),
2716 ];
2717
2718 let quals: &[_] = if check_pub {
2723 ALL_QUALS
2724 } else {
2725 &[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)]
2726 };
2727 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))
2730 && self.look_ahead(1, |t| {
2731 t.is_keyword_case(kw::Fn, case)
2733 || (
2735 (
2736 t.is_non_raw_ident_where(|i|
2737 quals.iter().any(|exp| exp.kw == i.name)
2738 && i.is_reserved()
2740 )
2741 || case == Case::Insensitive
2742 && t.is_non_raw_ident_where(|i| quals.iter().any(|exp| {
2743 exp.kw.as_str() == i.name.as_str().to_lowercase()
2744 }))
2745 )
2746 && !self.is_unsafe_foreign_mod()
2748 && !self.is_async_gen_block()
2750 && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait])
2752 )
2753 })
2754 || 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)
2756 && self.look_ahead(1, |t| t.can_begin_string_literal())
2760 && (self.tree_look_ahead(2, |tt| {
2761 match tt {
2762 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
2763 TokenTree::Delimited(..) => false,
2764 }
2765 }) == Some(true) ||
2766 (self.may_recover()
2769 && self.tree_look_ahead(2, |tt| {
2770 match tt {
2771 TokenTree::Token(t, _) =>
2772 ALL_QUALS.iter().any(|exp| {
2773 t.is_keyword(exp.kw)
2774 }),
2775 TokenTree::Delimited(..) => false,
2776 }
2777 }) == Some(true)
2778 && self.tree_look_ahead(3, |tt| {
2779 match tt {
2780 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
2781 TokenTree::Delimited(..) => false,
2782 }
2783 }) == Some(true)
2784 )
2785 )
2786 }
2787
2788 pub(super) fn parse_fn_front_matter(
2803 &mut self,
2804 orig_vis: &Visibility,
2805 case: Case,
2806 parsing_mode: FrontMatterParsingMode,
2807 ) -> PResult<'a, FnHeader> {
2808 let sp_start = self.token.span;
2809 let constness = self.parse_constness(case);
2810 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
2811 && let Const::Yes(const_span) = constness
2812 {
2813 self.dcx().emit_err(FnPointerCannotBeConst {
2814 span: const_span,
2815 suggestion: const_span.until(self.token.span),
2816 });
2817 }
2818
2819 let async_start_sp = self.token.span;
2820 let coroutine_kind = self.parse_coroutine_kind(case);
2821 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
2822 && let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind
2823 {
2824 self.dcx().emit_err(FnPointerCannotBeAsync {
2825 span: async_span,
2826 suggestion: async_span.until(self.token.span),
2827 });
2828 }
2829 let unsafe_start_sp = self.token.span;
2832 let safety = self.parse_safety(case);
2833
2834 let ext_start_sp = self.token.span;
2835 let ext = self.parse_extern(case);
2836
2837 if let Some(CoroutineKind::Async { span, .. }) = coroutine_kind {
2838 if span.is_rust_2015() {
2839 self.dcx().emit_err(errors::AsyncFnIn2015 {
2840 span,
2841 help: errors::HelpUseLatestEdition::new(),
2842 });
2843 }
2844 }
2845
2846 match coroutine_kind {
2847 Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
2848 self.psess.gated_spans.gate(sym::gen_blocks, span);
2849 }
2850 Some(CoroutineKind::Async { .. }) | None => {}
2851 }
2852
2853 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) {
2854 match self.expect_one_of(&[], &[]) {
2858 Ok(Recovered::Yes(_)) => {}
2859 Ok(Recovered::No) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
2860 Err(mut err) => {
2861 enum WrongKw {
2863 Duplicated(Span),
2864 Misplaced(Span),
2865 MisplacedDisallowedQualifier,
2870 }
2871
2872 let mut recover_constness = constness;
2874 let mut recover_coroutine_kind = coroutine_kind;
2875 let mut recover_safety = safety;
2876 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)) {
2879 match constness {
2880 Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
2881 Const::No => {
2882 recover_constness = Const::Yes(self.token.span);
2883 match parsing_mode {
2884 FrontMatterParsingMode::Function => {
2885 Some(WrongKw::Misplaced(async_start_sp))
2886 }
2887 FrontMatterParsingMode::FunctionPtrType => {
2888 self.dcx().emit_err(FnPointerCannotBeConst {
2889 span: self.token.span,
2890 suggestion: self
2891 .token
2892 .span
2893 .with_lo(self.prev_token.span.hi()),
2894 });
2895 Some(WrongKw::MisplacedDisallowedQualifier)
2896 }
2897 }
2898 }
2899 }
2900 } 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)) {
2901 match coroutine_kind {
2902 Some(CoroutineKind::Async { span, .. }) => {
2903 Some(WrongKw::Duplicated(span))
2904 }
2905 Some(CoroutineKind::AsyncGen { span, .. }) => {
2906 Some(WrongKw::Duplicated(span))
2907 }
2908 Some(CoroutineKind::Gen { .. }) => {
2909 recover_coroutine_kind = Some(CoroutineKind::AsyncGen {
2910 span: self.token.span,
2911 closure_id: DUMMY_NODE_ID,
2912 return_impl_trait_id: DUMMY_NODE_ID,
2913 });
2914 Some(WrongKw::Misplaced(unsafe_start_sp))
2916 }
2917 None => {
2918 recover_coroutine_kind = Some(CoroutineKind::Async {
2919 span: self.token.span,
2920 closure_id: DUMMY_NODE_ID,
2921 return_impl_trait_id: DUMMY_NODE_ID,
2922 });
2923 match parsing_mode {
2924 FrontMatterParsingMode::Function => {
2925 Some(WrongKw::Misplaced(async_start_sp))
2926 }
2927 FrontMatterParsingMode::FunctionPtrType => {
2928 self.dcx().emit_err(FnPointerCannotBeAsync {
2929 span: self.token.span,
2930 suggestion: self
2931 .token
2932 .span
2933 .with_lo(self.prev_token.span.hi()),
2934 });
2935 Some(WrongKw::MisplacedDisallowedQualifier)
2936 }
2937 }
2938 }
2939 }
2940 } 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)) {
2941 match safety {
2942 Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
2943 Safety::Safe(sp) => {
2944 recover_safety = Safety::Unsafe(self.token.span);
2945 Some(WrongKw::Misplaced(sp))
2946 }
2947 Safety::Default => {
2948 recover_safety = Safety::Unsafe(self.token.span);
2949 Some(WrongKw::Misplaced(ext_start_sp))
2950 }
2951 }
2952 } 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)) {
2953 match safety {
2954 Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
2955 Safety::Unsafe(sp) => {
2956 recover_safety = Safety::Safe(self.token.span);
2957 Some(WrongKw::Misplaced(sp))
2958 }
2959 Safety::Default => {
2960 recover_safety = Safety::Safe(self.token.span);
2961 Some(WrongKw::Misplaced(ext_start_sp))
2962 }
2963 }
2964 } else {
2965 None
2966 };
2967
2968 if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw {
2970 let original_kw = self
2971 .span_to_snippet(original_sp)
2972 .expect("Span extracted directly from keyword should always work");
2973
2974 err.span_suggestion(
2975 self.token_uninterpolated_span(),
2976 ::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"),
2977 "",
2978 Applicability::MachineApplicable,
2979 )
2980 .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"));
2981 }
2982 else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
2984 let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
2985 if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
2986 let misplaced_qual_sp = self.token_uninterpolated_span();
2987 let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
2988
2989 err.span_suggestion(
2990 correct_pos_sp.to(misplaced_qual_sp),
2991 ::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}`"),
2992 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", misplaced_qual,
current_qual))
})format!("{misplaced_qual} {current_qual}"),
2993 Applicability::MachineApplicable,
2994 ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
2995 }
2996 }
2997 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)) {
2999 let sp = sp_start.to(self.prev_token.span);
3000 if let Ok(snippet) = self.span_to_snippet(sp) {
3001 let current_vis = match self.parse_visibility(FollowedByType::No) {
3002 Ok(v) => v,
3003 Err(d) => {
3004 d.cancel();
3005 return Err(err);
3006 }
3007 };
3008 let vs = pprust::vis_to_string(¤t_vis);
3009 let vs = vs.trim_end();
3010
3011 if #[allow(non_exhaustive_omitted_patterns)] match orig_vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(orig_vis.kind, VisibilityKind::Inherited) {
3013 err.span_suggestion(
3014 sp_start.to(self.prev_token.span),
3015 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("visibility `{0}` must come before `{1}`",
vs, snippet))
})format!("visibility `{vs}` must come before `{snippet}`"),
3016 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", vs, snippet))
})format!("{vs} {snippet}"),
3017 Applicability::MachineApplicable,
3018 );
3019 }
3020 else {
3022 err.span_suggestion(
3023 current_vis.span,
3024 "there is already a visibility modifier, remove one",
3025 "",
3026 Applicability::MachineApplicable,
3027 )
3028 .span_note(orig_vis.span, "explicit visibility first seen here");
3029 }
3030 }
3031 }
3032
3033 if let Some(wrong_kw) = wrong_kw
3036 && self.may_recover()
3037 && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
3038 {
3039 self.bump();
3041 self.bump();
3042 if #[allow(non_exhaustive_omitted_patterns)] match wrong_kw {
WrongKw::MisplacedDisallowedQualifier => true,
_ => false,
}matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
3045 err.cancel();
3046 } else {
3047 err.emit();
3048 }
3049 return Ok(FnHeader {
3050 constness: recover_constness,
3051 safety: recover_safety,
3052 coroutine_kind: recover_coroutine_kind,
3053 ext,
3054 });
3055 }
3056
3057 return Err(err);
3058 }
3059 }
3060 }
3061
3062 Ok(FnHeader { constness, safety, coroutine_kind, ext })
3063 }
3064
3065 pub(super) fn parse_fn_decl(
3067 &mut self,
3068 fn_parse_mode: &FnParseMode,
3069 ret_allow_plus: AllowPlus,
3070 recover_return_sign: RecoverReturnSign,
3071 ) -> PResult<'a, Box<FnDecl>> {
3072 Ok(Box::new(FnDecl {
3073 inputs: self.parse_fn_params(fn_parse_mode)?,
3074 output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
3075 }))
3076 }
3077
3078 pub(super) fn parse_fn_params(
3080 &mut self,
3081 fn_parse_mode: &FnParseMode,
3082 ) -> PResult<'a, ThinVec<Param>> {
3083 let mut first_param = true;
3084 if self.token != TokenKind::OpenParen
3086 && !self.token.is_keyword(kw::For)
3088 {
3089 self.dcx()
3091 .emit_err(errors::MissingFnParams { span: self.prev_token.span.shrink_to_hi() });
3092 return Ok(ThinVec::new());
3093 }
3094
3095 let (mut params, _) = self.parse_paren_comma_seq(|p| {
3096 p.recover_vcs_conflict_marker();
3097 let snapshot = p.create_snapshot_for_diagnostic();
3098 let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| {
3099 let guar = e.emit();
3100 let lo = if let TokenKind::OpenParen = p.prev_token.kind {
3104 p.prev_token.span.shrink_to_hi()
3105 } else {
3106 p.prev_token.span
3107 };
3108 p.restore_snapshot(snapshot);
3109 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)]);
3111 Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
3113 });
3114 first_param = false;
3116 param
3117 })?;
3118 self.deduplicate_recovered_params_names(&mut params);
3120 Ok(params)
3121 }
3122
3123 pub(super) fn parse_param_general(
3128 &mut self,
3129 fn_parse_mode: &FnParseMode,
3130 first_param: bool,
3131 recover_arg_parse: bool,
3132 ) -> PResult<'a, Param> {
3133 let lo = self.token.span;
3134 let attrs = self.parse_outer_attributes()?;
3135 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3136 if let Some(mut param) = this.parse_self_param()? {
3138 param.attrs = attrs;
3139 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
3140 return Ok((res?, Trailing::No, UsePreAttrPos::No));
3141 }
3142
3143 let is_dot_dot_dot = if this.token.kind == token::DotDotDot {
3144 IsDotDotDot::Yes
3145 } else {
3146 IsDotDotDot::No
3147 };
3148 let is_name_required = (fn_parse_mode.req_name)(
3149 this.token.span.with_neighbor(this.prev_token.span).edition(),
3150 is_dot_dot_dot,
3151 );
3152 let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes {
3153 this.psess.buffer_lint(
3154 VARARGS_WITHOUT_PATTERN,
3155 this.token.span,
3156 ast::CRATE_NODE_ID,
3157 errors::VarargsWithoutPattern { span: this.token.span },
3158 );
3159 false
3160 } else {
3161 is_name_required
3162 };
3163 let (pat, ty) = if is_name_required || this.is_named_param() {
3164 {
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/item.rs:3164",
"rustc_parse::parser::item", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_parse/src/parser/item.rs"),
::tracing_core::__macro_support::Option::Some(3164u32),
::tracing_core::__macro_support::Option::Some("rustc_parse::parser::item"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("parse_param_general parse_pat (is_name_required:{0})",
is_name_required) as &dyn Value))])
});
} else { ; }
};debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
3165 let (pat, colon) = this.parse_fn_param_pat_colon()?;
3166 if !colon {
3167 let mut err = this.unexpected().unwrap_err();
3168 return if let Some(ident) = this.parameter_without_type(
3169 &mut err,
3170 pat,
3171 is_name_required,
3172 first_param,
3173 fn_parse_mode,
3174 ) {
3175 let guar = err.emit();
3176 Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No))
3177 } else {
3178 Err(err)
3179 };
3180 }
3181
3182 this.eat_incorrect_doc_comment_for_param_type();
3183 (pat, this.parse_ty_for_param()?)
3184 } else {
3185 {
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/item.rs:3185",
"rustc_parse::parser::item", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_parse/src/parser/item.rs"),
::tracing_core::__macro_support::Option::Some(3185u32),
::tracing_core::__macro_support::Option::Some("rustc_parse::parser::item"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("parse_param_general ident_to_pat")
as &dyn Value))])
});
} else { ; }
};debug!("parse_param_general ident_to_pat");
3186 let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
3187 this.eat_incorrect_doc_comment_for_param_type();
3188 let mut ty = this.parse_ty_for_param();
3189
3190 if let Ok(t) = &ty {
3191 if let TyKind::Path(_, Path { segments, .. }) = &t.kind
3193 && let Some(segment) = segments.last()
3194 && let Some(guar) =
3195 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)])
3196 {
3197 return Ok((
3198 dummy_arg(segment.ident, guar),
3199 Trailing::No,
3200 UsePreAttrPos::No,
3201 ));
3202 }
3203
3204 if this.token != token::Comma && this.token != token::CloseParen {
3205 ty = this.unexpected_any();
3208 }
3209 }
3210 match ty {
3211 Ok(ty) => {
3212 let pat = this.mk_pat(ty.span, PatKind::Missing);
3213 (Box::new(pat), ty)
3214 }
3215 Err(err) if this.token == token::DotDotDot => return Err(err),
3217 Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
3218 Err(err) if recover_arg_parse => {
3219 err.cancel();
3221 this.restore_snapshot(parser_snapshot_before_ty);
3222 this.recover_arg_parse()?
3223 }
3224 Err(err) => return Err(err),
3225 }
3226 };
3227
3228 let span = lo.to(this.prev_token.span);
3229
3230 Ok((
3231 Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
3232 Trailing::No,
3233 UsePreAttrPos::No,
3234 ))
3235 })
3236 }
3237
3238 fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
3240 let expect_self_ident = |this: &mut Self| match this.token.ident() {
3242 Some((ident, IdentIsRaw::No)) => {
3243 this.bump();
3244 ident
3245 }
3246 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3247 };
3248 let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime());
3250 let is_isolated_self = |this: &Self, n| {
3252 this.is_keyword_ahead(n, &[kw::SelfLower])
3253 && this.look_ahead(n + 1, |t| t != &token::PathSep)
3254 };
3255 let is_isolated_pin_const_self = |this: &Self, n| {
3257 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3258 && this.is_keyword_ahead(n + 1, &[kw::Const])
3259 && is_isolated_self(this, n + 2)
3260 };
3261 let is_isolated_mut_self =
3263 |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
3264 let is_isolated_pin_mut_self = |this: &Self, n| {
3266 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3267 && is_isolated_mut_self(this, n + 1)
3268 };
3269 let parse_self_possibly_typed = |this: &mut Self, m| {
3271 let eself_ident = expect_self_ident(this);
3272 let eself_hi = this.prev_token.span;
3273 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)) {
3274 SelfKind::Explicit(this.parse_ty()?, m)
3275 } else {
3276 SelfKind::Value(m)
3277 };
3278 Ok((eself, eself_ident, eself_hi))
3279 };
3280 let expect_self_ident_not_typed =
3281 |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
3282 let eself_ident = expect_self_ident(this);
3283
3284 if this.may_recover() && this.eat_noexpect(&token::Colon) {
3286 let snap = this.create_snapshot_for_diagnostic();
3287 match this.parse_ty() {
3288 Ok(ty) => {
3289 this.dcx().emit_err(errors::IncorrectTypeOnSelf {
3290 span: ty.span,
3291 move_self_modifier: errors::MoveSelfModifier {
3292 removal_span: modifier_span,
3293 insertion_span: ty.span.shrink_to_lo(),
3294 modifier: modifier.to_ref_suggestion(),
3295 },
3296 });
3297 }
3298 Err(diag) => {
3299 diag.cancel();
3300 this.restore_snapshot(snap);
3301 }
3302 }
3303 }
3304 eself_ident
3305 };
3306 let recover_self_ptr = |this: &mut Self| {
3308 this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
3309
3310 Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
3311 };
3312
3313 let eself_lo = self.token.span;
3317 let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
3318 token::And => {
3319 let has_lifetime = is_lifetime(self, 1);
3320 let skip_lifetime_count = has_lifetime as usize;
3321 let eself = if is_isolated_self(self, skip_lifetime_count + 1) {
3322 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3325 SelfKind::Region(lifetime, Mutability::Not)
3326 } else if is_isolated_mut_self(self, skip_lifetime_count + 1) {
3327 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3330 self.bump(); SelfKind::Region(lifetime, Mutability::Mut)
3332 } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) {
3333 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3336 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3337 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Not)
3340 } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) {
3341 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3344 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3345 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Mut)
3348 } else {
3349 return Ok(None);
3351 };
3352 let hi = self.token.span;
3353 let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
3354 (eself, self_ident, hi)
3355 }
3356 token::Star if is_isolated_self(self, 1) => {
3358 self.bump();
3359 recover_self_ptr(self)?
3360 }
3361 token::Star
3363 if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
3364 {
3365 self.bump();
3366 self.bump();
3367 recover_self_ptr(self)?
3368 }
3369 token::Ident(..) if is_isolated_self(self, 0) => {
3371 parse_self_possibly_typed(self, Mutability::Not)?
3372 }
3373 token::Ident(..) if is_isolated_mut_self(self, 0) => {
3375 self.bump();
3376 parse_self_possibly_typed(self, Mutability::Mut)?
3377 }
3378 _ => return Ok(None),
3379 };
3380
3381 let eself = source_map::respan(eself_lo.to(eself_hi), eself);
3382 Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
3383 }
3384
3385 fn is_named_param(&self) -> bool {
3386 let offset = match &self.token.kind {
3387 token::OpenInvisible(origin) => match origin {
3388 InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
3389 return self.check_noexpect_past_close_delim(&token::Colon);
3390 }
3391 _ => 0,
3392 },
3393 token::And | token::AndAnd => 1,
3394 _ if self.token.is_keyword(kw::Mut) => 1,
3395 _ => 0,
3396 };
3397
3398 self.look_ahead(offset, |t| t.is_ident())
3399 && self.look_ahead(offset + 1, |t| t == &token::Colon)
3400 }
3401
3402 fn recover_self_param(&mut self) -> bool {
3403 #[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!(
3404 self.parse_outer_attributes()
3405 .and_then(|_| self.parse_self_param())
3406 .map_err(|e| e.cancel()),
3407 Ok(Some(_))
3408 )
3409 }
3410}
3411
3412enum IsMacroRulesItem {
3413 Yes { has_bang: bool },
3414 No,
3415}
3416
3417#[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_receiver_is_total_eq(&self) -> () {}
}Eq)]
3418pub(super) enum FrontMatterParsingMode {
3419 Function,
3421 FunctionPtrType,
3424}