1use std::fmt::Write;
2use std::mem;
3
4use ast::token::IdentIsRaw;
5use rustc_ast as ast;
6use rustc_ast::ast::*;
7use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
8use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
9use rustc_ast::util::case::Case;
10use rustc_ast_pretty::pprust;
11use rustc_errors::codes::*;
12use rustc_errors::{Applicability, PResult, StashKey, msg, struct_span_code_err};
13use rustc_session::lint::builtin::VARARGS_WITHOUT_PATTERN;
14use rustc_span::edit_distance::edit_distance;
15use rustc_span::edition::Edition;
16use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, respan, sym};
17use thin_vec::{ThinVec, thin_vec};
18use tracing::debug;
19
20use super::diagnostics::{ConsumeClosingDelim, dummy_arg};
21use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
22use super::{
23 AllowConstBlockItems, AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect,
24 Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,
25};
26use crate::diagnostics::{
27 self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField,
28 UseDoubleColonSuggestion, UseRegularStructSuggestion,
29};
30use crate::exp;
31
32impl<'a> Parser<'a> {
33 pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
35 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))?;
36 Ok(ast::Crate { attrs, items, spans, id: DUMMY_NODE_ID, is_placeholder: false })
37 }
38
39 fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
41 let safety = self.parse_safety(Case::Sensitive);
42 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mod,
token_type: crate::parser::token_type::TokenType::KwMod,
}exp!(Mod))?;
43 let ident = self.parse_ident()?;
44 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)) {
45 ModKind::Unloaded
46 } else {
47 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
48 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))?;
49 attrs.extend(inner_attrs);
50 ModKind::Loaded(items, Inline::Yes, inner_span)
51 };
52 Ok(ItemKind::Mod(safety, ident, mod_kind))
53 }
54
55 pub fn parse_mod(
60 &mut self,
61 term: ExpTokenPair,
62 ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
63 let lo = self.token.span;
64 let attrs = self.parse_inner_attributes()?;
65
66 let post_attr_lo = self.token.span;
67 let mut items: ThinVec<Box<_>> = ThinVec::new();
68
69 loop {
72 while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else {
74 break;
75 };
76 items.push(item);
77 }
78
79 if !self.eat(term) {
80 let token_str = super::token_descr(&self.token);
81 if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
82 let is_let = self.token.is_keyword(kw::Let);
83 let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
84 let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);
85
86 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected item, found {0}",
token_str))
})format!("expected item, found {token_str}");
87 let mut err = self.dcx().struct_span_err(self.token.span, msg);
88
89 let label = if is_let {
90 "`let` cannot be used for global variables"
91 } else {
92 "expected item"
93 };
94 err.span_label(self.token.span, label);
95
96 if is_let {
97 if is_let_mut {
98 err.help("consider using `static` and a `Mutex` instead of `let mut`");
99 } else if let_has_ident {
100 err.span_suggestion_short(
101 self.token.span,
102 "consider using `static` or `const` instead of `let`",
103 "static",
104 Applicability::MaybeIncorrect,
105 );
106 } else {
107 err.help("consider using `static` or `const` instead of `let`");
108 }
109 }
110 err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
111 return Err(err);
112 }
113 }
114
115 let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo());
116 let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };
117 Ok((attrs, items, mod_spans))
118 }
119}
120
121enum ReuseKind {
122 Path,
123 Impl,
124}
125
126impl<'a> Parser<'a> {
127 pub fn parse_item(
128 &mut self,
129 force_collect: ForceCollect,
130 allow_const_block_items: AllowConstBlockItems,
131 ) -> PResult<'a, Option<Box<Item>>> {
132 let fn_parse_mode =
133 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
134 self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items)
135 .map(|i| i.map(Box::new))
136 }
137
138 fn parse_item_(
139 &mut self,
140 fn_parse_mode: FnParseMode,
141 force_collect: ForceCollect,
142 const_block_items_allowed: AllowConstBlockItems,
143 ) -> PResult<'a, Option<Item>> {
144 self.recover_vcs_conflict_marker();
145 let attrs = self.parse_outer_attributes()?;
146 self.recover_vcs_conflict_marker();
147 self.parse_item_common(
148 attrs,
149 true,
150 false,
151 fn_parse_mode,
152 force_collect,
153 const_block_items_allowed,
154 )
155 }
156
157 pub(super) fn parse_item_common(
158 &mut self,
159 attrs: AttrWrapper,
160 mac_allowed: bool,
161 attrs_allowed: bool,
162 fn_parse_mode: FnParseMode,
163 force_collect: ForceCollect,
164 allow_const_block_items: AllowConstBlockItems,
165 ) -> PResult<'a, Option<Item>> {
166 if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| {
167 this.parse_item(ForceCollect::Yes, allow_const_block_items)
168 }) {
169 let mut item = item.expect("an actual item");
170 attrs.prepend_to_nt_inner(&mut item.attrs);
171 return Ok(Some(*item));
172 }
173
174 self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {
175 let lo = this.token.span;
176 let vis = this.parse_visibility(FollowedByType::No)?;
177 let mut def = this.parse_defaultness();
178 let kind = this.parse_item_kind(
179 &mut attrs,
180 mac_allowed,
181 allow_const_block_items,
182 lo,
183 &vis,
184 &mut def,
185 fn_parse_mode,
186 Case::Sensitive,
187 )?;
188 if let Some(kind) = kind {
189 this.error_on_unconsumed_default(def, &kind);
190 let span = lo.to(this.prev_token.span);
191 let id = DUMMY_NODE_ID;
192 let item = Item { attrs, id, kind, vis, span, tokens: None };
193 return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
194 }
195
196 if !#[allow(non_exhaustive_omitted_patterns)] match vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(vis.kind, VisibilityKind::Inherited) {
198 let vis_str = pprust::vis_to_string(&vis).trim_end().to_string();
199 let mut err = this.dcx().create_err(diagnostics::VisibilityNotFollowedByItem {
200 span: vis.span,
201 vis: vis_str,
202 });
203 if let Some((ident, _)) = this.token.ident()
204 && !ident.is_used_keyword()
205 && let Some((similar_kw, is_incorrect_case)) = ident
206 .name
207 .find_similar(&rustc_span::symbol::used_keywords(|| ident.span.edition()))
208 {
209 err.subdiagnostic(diagnostics::MisspelledKw {
210 similar_kw: similar_kw.to_string(),
211 span: ident.span,
212 is_incorrect_case,
213 });
214 }
215 err.emit();
216 }
217
218 if let Defaultness::Default(span) = def {
219 this.dcx().emit_err(diagnostics::DefaultNotFollowedByItem { span });
220 } else if let Defaultness::Final(span) = def {
221 this.dcx().emit_err(diagnostics::FinalNotFollowedByItem { span });
222 }
223
224 if !attrs_allowed {
225 this.recover_attrs_no_item(&attrs)?;
226 }
227 Ok((None, Trailing::No, UsePreAttrPos::No))
228 })
229 }
230
231 fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
233 match def {
234 Defaultness::Default(span) => {
235 self.dcx().emit_err(diagnostics::InappropriateDefault {
236 span,
237 article: kind.article(),
238 descr: kind.descr(),
239 });
240 }
241 Defaultness::Final(span) => {
242 self.dcx().emit_err(diagnostics::InappropriateFinal {
243 span,
244 article: kind.article(),
245 descr: kind.descr(),
246 });
247 }
248 Defaultness::Implicit => (),
249 }
250 }
251
252 fn parse_item_kind(
254 &mut self,
255 attrs: &mut AttrVec,
256 macros_allowed: bool,
257 allow_const_block_items: AllowConstBlockItems,
258 lo: Span,
259 vis: &Visibility,
260 def: &mut Defaultness,
261 fn_parse_mode: FnParseMode,
262 case: Case,
263 ) -> PResult<'a, Option<ItemKind>> {
264 let check_pub = def == &Defaultness::Implicit;
265 let mut def_ = || mem::replace(def, Defaultness::Implicit);
266
267 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) {
268 self.parse_use_item()?
269 } else if self.check_fn_front_matter(check_pub, case) {
270 let defaultness = def_();
272 if let Defaultness::Default(span) = defaultness {
273 self.psess.gated_spans.gate(sym::min_specialization, span);
277 self.psess.gated_spans.ungate_last(sym::specialization, span);
278 }
279 let (ident, sig, generics, contract, body) =
280 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
281 ItemKind::Fn(Box::new(Fn {
282 defaultness,
283 ident,
284 sig,
285 generics,
286 contract,
287 body,
288 define_opaque: None,
289 eii_impls: ThinVec::new(),
290 }))
291 } 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) {
292 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) {
293 self.parse_item_extern_crate()?
295 } else {
296 self.parse_item_foreign_mod(attrs, Safety::Default)?
298 }
299 } else if self.is_unsafe_foreign_mod() {
300 let safety = self.parse_safety(Case::Sensitive);
302 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern))?;
303 self.parse_item_foreign_mod(attrs, safety)?
304 } else if let Some(safety) = self.parse_global_static_front_matter(case) {
305 let mutability = self.parse_mutability();
307 self.parse_static_item(safety, mutability)?
308 } 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() {
309 self.parse_item_trait(attrs, lo)?
311 } else if self.check_impl_frontmatter(0) {
312 self.parse_item_impl(attrs, def_(), false)?
314 } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
315 allow_const_block_items
316 && self.check_inline_const(0)
317 {
318 if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
320 {
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:320",
"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(320u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Parsing a const block item that does not matter: {0:?}",
self.token.span) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("Parsing a const block item that does not matter: {:?}", self.token.span);
321 };
322 ItemKind::ConstBlock(self.parse_const_block_item()?)
323 } else if let Const::Yes(const_span) = self.parse_constness(case) {
324 self.recover_const_mut(const_span);
326 self.recover_missing_kw_before_item()?;
327 let (ident, generics, ty, body) = self.parse_const_item(const_span)?;
328 ItemKind::Const(Box::new(ConstItem {
329 defaultness: def_(),
330 ident,
331 generics,
332 ty,
333 body,
334 kind: ConstItemKind::Body,
335 define_opaque: None,
336 }))
337 } else if let Some(kind) = self.is_reuse_item() {
338 self.parse_item_delegation(attrs, def_(), kind)?
339 } 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)
340 || 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])
341 {
342 self.parse_item_mod(attrs)?
344 } 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) {
345 if let Const::Yes(const_span) = self.parse_constness(case) {
346 self.recover_const_mut(const_span);
348 self.recover_missing_kw_before_item()?;
349 let (ident, generics, ty, body) = self.parse_const_item(const_span)?;
350 self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span));
353 ItemKind::Const(Box::new(ConstItem {
354 defaultness: def_(),
355 ident,
356 generics,
357 ty,
358 body,
359 kind: ConstItemKind::TypeConst,
360 define_opaque: None,
361 }))
362 } else {
363 self.parse_type_alias(def_())?
365 }
366 } 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) {
367 self.parse_item_enum()?
369 } 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) {
370 self.parse_item_struct()?
372 } else if self.is_kw_followed_by_ident(kw::Union) {
373 self.bump(); self.parse_item_union()?
376 } else if self.is_builtin() {
377 return self.parse_item_builtin();
379 } 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) {
380 self.parse_item_decl_macro(lo)?
382 } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
383 self.parse_item_macro_rules(vis, has_bang)?
385 } else if self.isnt_macro_invocation()
386 && (self.token.is_ident_named(sym::import)
387 || self.token.is_ident_named(sym::using)
388 || self.token.is_ident_named(sym::include)
389 || self.token.is_ident_named(sym::require))
390 {
391 return self.recover_import_as_use();
392 } else if self.isnt_macro_invocation() && vis.kind.is_pub() {
393 self.recover_missing_kw_before_item()?;
394 return Ok(None);
395 } else if self.isnt_macro_invocation() && case == Case::Sensitive {
396 _ = def_;
397
398 return self.parse_item_kind(
400 attrs,
401 macros_allowed,
402 allow_const_block_items,
403 lo,
404 vis,
405 def,
406 fn_parse_mode,
407 Case::Insensitive,
408 );
409 } else if macros_allowed && self.check_path() {
410 if self.isnt_macro_invocation() {
411 self.recover_missing_kw_before_item()?;
412 }
413 ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
415 } else {
416 return Ok(None);
417 };
418 Ok(Some(info))
419 }
420
421 fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
422 let span = self.token.span;
423 let token_name = super::token_descr(&self.token);
424 let snapshot = self.create_snapshot_for_diagnostic();
425 self.bump();
426 match self.parse_use_item() {
427 Ok(u) => {
428 self.dcx().emit_err(diagnostics::RecoverImportAsUse { span, token_name });
429 Ok(Some(u))
430 }
431 Err(e) => {
432 e.cancel();
433 self.restore_snapshot(snapshot);
434 Ok(None)
435 }
436 }
437 }
438
439 fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
440 let tree = self.parse_use_tree()?;
441 if let Err(mut e) = self.expect_semi() {
442 match tree.kind {
443 UseTreeKind::Glob(_) => {
444 e.note("the wildcard token must be last on the path");
445 }
446 UseTreeKind::Nested { .. } => {
447 e.note("glob-like brace syntax must be last on the path");
448 }
449 _ => (),
450 }
451 return Err(e);
452 }
453 Ok(ItemKind::Use(tree))
454 }
455
456 pub(super) fn is_path_start_item(&mut self) -> bool {
458 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{..}) }
464
465 fn is_reuse_item(&mut self) -> Option<ReuseKind> {
466 if !self.token.is_keyword(kw::Reuse) {
467 return None;
468 }
469
470 if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
472 Some(ReuseKind::Path)
473 } else if self.check_impl_frontmatter(1) {
474 Some(ReuseKind::Impl)
475 } else {
476 None
477 }
478 }
479
480 fn isnt_macro_invocation(&mut self) -> bool {
482 self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
483 }
484
485 fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
488 let is_pub = self.prev_token.is_keyword(kw::Pub);
489 let is_const = self.prev_token.is_keyword(kw::Const);
490 let ident_span = self.token.span;
491 let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };
492 let insert_span = ident_span.shrink_to_lo();
493
494 let ident = if self.token.is_ident()
495 && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
496 && self.look_ahead(1, |t| {
497 #[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)
498 }) {
499 self.parse_ident_common(true).unwrap()
500 } else {
501 return Ok(());
502 };
503
504 let mut found_generics = false;
505 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Lt,
token_type: crate::parser::token_type::TokenType::Lt,
}exp!(Lt)) {
506 found_generics = true;
507 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Gt,
token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)]);
508 self.bump(); }
510
511 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)) {
512 if self.look_ahead(1, |t| *t == token::CloseBrace) {
514 Some(diagnostics::MissingKeywordForItemDefinition::EnumOrStruct { span })
516 } else if self.look_ahead(2, |t| *t == token::Colon)
517 || self.look_ahead(3, |t| *t == token::Colon)
518 {
519 Some(diagnostics::MissingKeywordForItemDefinition::Struct {
521 span,
522 insert_span,
523 ident,
524 })
525 } else {
526 Some(diagnostics::MissingKeywordForItemDefinition::Enum {
527 span,
528 insert_span,
529 ident,
530 })
531 }
532 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
533 self.bump(); let is_method = self.recover_self_param();
536
537 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);
538
539 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)) {
540 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)]);
541 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);
543 if is_method {
544 diagnostics::MissingKeywordForItemDefinition::Method {
545 span,
546 insert_span,
547 ident,
548 }
549 } else {
550 diagnostics::MissingKeywordForItemDefinition::Function {
551 span,
552 insert_span,
553 ident,
554 }
555 }
556 } 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)) {
557 diagnostics::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
558 } else {
559 diagnostics::MissingKeywordForItemDefinition::Ambiguous {
560 span,
561 subdiag: if found_generics {
562 None
563 } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
564 Some(diagnostics::AmbiguousMissingKwForItemSub::SuggestMacro {
565 span: ident_span,
566 snippet,
567 })
568 } else {
569 Some(diagnostics::AmbiguousMissingKwForItemSub::HelpMacro)
570 },
571 }
572 };
573 Some(err)
574 } else if found_generics {
575 Some(diagnostics::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
576 } else {
577 None
578 };
579
580 if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
581 }
582
583 fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
584 Ok(None)
586 }
587
588 fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
590 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() {
593 Ok(args) => {
595 self.eat_semi_for_macro_if_needed(&args, Some(&path));
596 self.complain_if_pub_macro(vis, false);
597 Ok(MacCall { path, args })
598 }
599
600 Err(mut err) => {
601 if self.token.is_ident()
603 && let [segment] = path.segments.as_slice()
604 && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
605 {
606 err.span_suggestion(
607 path.span,
608 "perhaps you meant to define a macro",
609 "macro_rules",
610 Applicability::MachineApplicable,
611 );
612 }
613 Err(err)
614 }
615 }
616 }
617
618 fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
620 let ([start @ end] | [start, .., end]) = attrs else {
621 return Ok(());
622 };
623 let msg = if end.is_doc_comment() {
624 "expected item after doc comment"
625 } else {
626 "expected item after attributes"
627 };
628 let mut err = self.dcx().struct_span_err(end.span, msg);
629 if end.is_doc_comment() {
630 err.span_label(end.span, "this doc comment doesn't document anything");
631 } else if self.token == TokenKind::Semi {
632 err.span_suggestion_verbose(
633 self.token.span,
634 "consider removing this semicolon",
635 "",
636 Applicability::MaybeIncorrect,
637 );
638 }
639 if let [.., penultimate, _] = attrs {
640 err.span_label(start.span.to(penultimate.span), "other attributes here");
641 }
642 Err(err)
643 }
644
645 fn is_async_fn(&self) -> bool {
646 self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
647 }
648
649 fn parse_polarity(&mut self) -> ast::ImplPolarity {
650 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()) {
652 self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
653 self.bump(); ast::ImplPolarity::Negative(self.prev_token.span)
655 } else {
656 ast::ImplPolarity::Positive
657 }
658 }
659
660 fn parse_item_impl(
675 &mut self,
676 attrs: &mut AttrVec,
677 defaultness: Defaultness,
678 is_reuse: bool,
679 ) -> PResult<'a, ItemKind> {
680 let constness = self.parse_constness(Case::Sensitive);
681 let safety = self.parse_safety(Case::Sensitive);
682 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
683 let mut generics_snapshot = None;
684 let mut generics = if self.choose_generics_over_qpath(0) {
686 self.parse_generics()?
687 } else {
688 if self.look_ahead(0, |t| t == &token::Lt)
691 && self.look_ahead(1, |t| t.is_ident())
692 && self.look_ahead(2, |t| t == &token::Lt)
693 {
694 generics_snapshot = Some(self.create_snapshot_for_diagnostic());
695 }
696
697 let mut generics = Generics::default();
698 generics.span = self.prev_token.span.shrink_to_hi();
701 generics
702 };
703
704 if let Const::Yes(span) = constness {
705 self.psess.gated_spans.gate(sym::const_trait_impl, span);
706 }
707
708 if (self.token_uninterpolated_span().at_least_rust_2018()
710 && self.token.is_keyword(kw::Async))
711 || self.is_kw_followed_by_ident(kw::Async)
712 {
713 self.bump();
714 self.dcx().emit_err(diagnostics::AsyncImpl { span: self.prev_token.span });
715 }
716
717 let polarity = self.parse_polarity();
718
719 let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
721 {
722 let span = self.prev_token.span.between(self.token.span);
723 return Err(self.dcx().create_err(diagnostics::MissingTraitInTraitImpl {
724 span,
725 for_span: span.to(self.token.span),
726 }));
727 } else {
728 self.parse_ty_with_generics_recovery(&generics).map_err(|e| {
729 let Some(mut snapshot) = generics_snapshot else {
730 return e;
731 };
732 snapshot.maybe_type_in_generic_parameter(e)
733 })?
734 };
735 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));
737 let missing_for_span = self.prev_token.span.between(self.token.span);
738
739 let ty_second = if self.token == token::DotDot {
740 self.bump(); Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
747 } else if has_for || self.token.can_begin_type() {
748 Some(self.parse_ty()?)
749 } else {
750 None
751 };
752
753 generics.where_clause = self.parse_where_clause()?;
754
755 let impl_items = if is_reuse {
756 Default::default()
757 } else {
758 self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
759 };
760
761 let (of_trait, self_ty) = match ty_second {
762 Some(ty_second) => {
763 if !has_for {
765 self.dcx()
766 .emit_err(diagnostics::MissingForInTraitImpl { span: missing_for_span });
767 }
768
769 let ty_first = *ty_first;
770 let path = match ty_first.kind {
771 TyKind::Path(None, path) => path,
773 other => {
774 if let TyKind::ImplTrait(_, bounds) = other
775 && let [bound] = bounds.as_slice()
776 && let GenericBound::Trait(poly_trait_ref) = bound
777 {
778 let extra_impl_kw = ty_first.span.until(bound.span());
782 self.dcx().emit_err(diagnostics::ExtraImplKeywordInTraitImpl {
783 extra_impl_kw,
784 impl_trait_span: ty_first.span,
785 });
786 poly_trait_ref.trait_ref.path.clone()
787 } else {
788 return Err(self.dcx().create_err(
789 diagnostics::ExpectedTraitInTraitImplFoundType {
790 span: ty_first.span,
791 },
792 ));
793 }
794 }
795 };
796 let trait_ref = TraitRef { path, ref_id: ty_first.id };
797
798 let of_trait =
799 Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
800 (of_trait, ty_second)
801 }
802 None => {
803 let self_ty = ty_first;
804 let error = |modifier, modifier_name, modifier_span| {
805 self.dcx().create_err(diagnostics::TraitImplModifierInInherentImpl {
806 span: self_ty.span,
807 modifier,
808 modifier_name,
809 modifier_span,
810 self_ty: self_ty.span,
811 })
812 };
813
814 if let Safety::Unsafe(span) = safety {
815 error("unsafe", "unsafe", span).with_code(E0197).emit();
816 }
817 if let ImplPolarity::Negative(span) = polarity {
818 error("!", "negative", span).emit();
819 }
820 if let Defaultness::Default(def_span) = defaultness {
821 error("default", "default", def_span).emit();
822 }
823 if let Const::Yes(span) = constness {
824 self.psess.gated_spans.gate(sym::const_trait_impl, span);
825 }
826 (None, self_ty)
827 }
828 };
829
830 Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
831 }
832
833 fn parse_item_delegation(
834 &mut self,
835 attrs: &mut AttrVec,
836 defaultness: Defaultness,
837 kind: ReuseKind,
838 ) -> PResult<'a, ItemKind> {
839 let span = self.token.span;
840 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Reuse,
token_type: crate::parser::token_type::TokenType::KwReuse,
}exp!(Reuse))?;
841
842 let item_kind = match kind {
843 ReuseKind::Path => self.parse_path_like_delegation(),
844 ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
845 }?;
846
847 self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
848
849 Ok(item_kind)
850 }
851
852 fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
853 Ok(if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
854 Some(self.parse_block()?)
855 } else {
856 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))?;
857 None
858 })
859 }
860
861 fn parse_impl_delegation(
862 &mut self,
863 span: Span,
864 attrs: &mut AttrVec,
865 defaultness: Defaultness,
866 ) -> PResult<'a, ItemKind> {
867 let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
868 let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
869
870 let until_expr_span = span.to(self.prev_token.span);
871
872 let Some(of_trait) = of_trait else {
873 return Err(self
874 .dcx()
875 .create_err(diagnostics::ImplReuseInherentImpl { span: until_expr_span }));
876 };
877
878 let body = self.parse_delegation_body()?;
879 let whole_reuse_span = span.to(self.prev_token.span);
880
881 items.push(Box::new(AssocItem {
882 id: DUMMY_NODE_ID,
883 attrs: Default::default(),
884 span: whole_reuse_span,
885 tokens: None,
886 vis: Visibility { kind: VisibilityKind::Inherited, span: whole_reuse_span },
887 kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
888 qself: None,
889 prefix: of_trait.trait_ref.path.clone(),
890 suffixes: DelegationSuffixes::Glob(whole_reuse_span),
891 body,
892 })),
893 }));
894
895 Ok(impl_item)
896 }
897
898 fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
899 let (qself, path) = if self.eat_lt() {
900 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
901 (Some(qself), path)
902 } else {
903 (None, self.parse_path(PathStyle::Expr)?)
904 };
905
906 let rename = |this: &mut Self| {
907 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 })
908 };
909
910 Ok(if self.eat_path_sep() {
911 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)) {
912 DelegationSuffixes::Glob(self.prev_token.span)
913 } else {
914 let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
915 DelegationSuffixes::List(
916 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,
917 )
918 };
919
920 ItemKind::DelegationMac(Box::new(DelegationMac {
921 qself,
922 prefix: path,
923 suffixes,
924 body: self.parse_delegation_body()?,
925 }))
926 } else {
927 let rename = rename(self)?;
928 let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
929
930 ItemKind::Delegation(Box::new(Delegation {
931 id: DUMMY_NODE_ID,
932 qself,
933 path,
934 ident,
935 rename,
936 body: self.parse_delegation_body()?,
937 source: DelegationSource::Single,
938 }))
939 })
940 }
941
942 fn parse_item_list<T>(
943 &mut self,
944 attrs: &mut AttrVec,
945 mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
946 ) -> PResult<'a, ThinVec<T>> {
947 let open_brace_span = self.token.span;
948
949 if self.token == TokenKind::Semi {
951 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
952 self.bump();
953 return Ok(ThinVec::new());
954 }
955
956 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
957 attrs.extend(self.parse_inner_attributes()?);
958
959 let mut items = ThinVec::new();
960 while !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)) {
961 if self.recover_doc_comment_before_brace() {
962 continue;
963 }
964 self.recover_vcs_conflict_marker();
965 match parse_item(self) {
966 Ok(None) => {
967 let mut is_unnecessary_semicolon = (self.token == token::Semi
968 && self.prev_token == token::Semi)
969 || !items.is_empty()
970 && self
988 .span_to_snippet(self.prev_token.span)
989 .is_ok_and(|snippet| snippet == "}")
990 && self.token == token::Semi;
991 let mut semicolon_span = self.token.span;
992 if !is_unnecessary_semicolon {
993 is_unnecessary_semicolon =
995 self.token == token::OpenBrace && self.prev_token == token::Semi;
996 semicolon_span = self.prev_token.span;
997 }
998 let non_item_span = self.token.span;
1000 let is_let = self.token.is_keyword(kw::Let);
1001
1002 let mut err =
1003 self.dcx().struct_span_err(non_item_span, "non-item in item list");
1004 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);
1005 if is_let {
1006 err.span_suggestion_verbose(
1007 non_item_span,
1008 "consider using `const` instead of `let` for associated const",
1009 "const",
1010 Applicability::MachineApplicable,
1011 );
1012 } else {
1013 err.span_label(open_brace_span, "item list starts here")
1014 .span_label(non_item_span, "non-item starts here")
1015 .span_label(self.prev_token.span, "item list ends here");
1016 }
1017 if is_unnecessary_semicolon {
1018 err.span_suggestion_verbose(
1019 semicolon_span,
1020 "consider removing this semicolon",
1021 "",
1022 Applicability::MaybeIncorrect,
1023 );
1024 }
1025 err.emit();
1026 break;
1027 }
1028 Ok(Some(item)) => items.extend(item),
1029 Err(err) => {
1030 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);
1031 err.with_span_label(
1032 open_brace_span,
1033 "while parsing this item list starting here",
1034 )
1035 .with_span_label(self.prev_token.span, "the item list ends here")
1036 .emit();
1037 break;
1038 }
1039 }
1040 }
1041 Ok(items)
1042 }
1043
1044 fn recover_doc_comment_before_brace(&mut self) -> bool {
1046 if let token::DocComment(..) = self.token.kind {
1047 if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
1048 {
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!(
1050 self.dcx(),
1051 self.token.span,
1052 E0584,
1053 "found a documentation comment that doesn't document anything",
1054 )
1055 .with_span_label(self.token.span, "this doc comment doesn't document anything")
1056 .with_help(
1057 "doc comments must come before what they document, if a comment was \
1058 intended use `//`",
1059 )
1060 .emit();
1061 self.bump();
1062 return true;
1063 }
1064 }
1065 false
1066 }
1067
1068 fn parse_defaultness(&mut self) -> Defaultness {
1070 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))
1074 && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
1075 {
1076 self.psess.gated_spans.gate(sym::specialization, self.token.span);
1077 self.bump(); Defaultness::Default(self.prev_token_uninterpolated_span())
1079 } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Final,
token_type: crate::parser::token_type::TokenType::KwFinal,
}exp!(Final)) {
1080 self.psess.gated_spans.gate(sym::final_associated_functions, self.prev_token.span);
1081 Defaultness::Final(self.prev_token_uninterpolated_span())
1082 } else {
1083 Defaultness::Implicit
1084 }
1085 }
1086
1087 fn check_trait_front_matter(&mut self) -> bool {
1089 const SUFFIXES: &[&[Symbol]] = &[
1090 &[kw::Trait],
1091 &[kw::Auto, kw::Trait],
1092 &[kw::Unsafe, kw::Trait],
1093 &[kw::Unsafe, kw::Auto, kw::Trait],
1094 &[kw::Const, kw::Trait],
1095 &[kw::Const, kw::Auto, kw::Trait],
1096 &[kw::Const, kw::Unsafe, kw::Trait],
1097 &[kw::Const, kw::Unsafe, kw::Auto, kw::Trait],
1098 ];
1099 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)) && self.look_ahead(1, |t| t == &token::OpenParen) {
1101 if self.is_keyword_ahead(2, &[kw::In]) {
1103 return true;
1104 }
1105 if self.is_keyword_ahead(2, &[kw::Crate, kw::SelfLower, kw::Super])
1107 && self.look_ahead(3, |t| t == &token::CloseParen)
1108 && SUFFIXES.iter().any(|suffix| {
1109 suffix.iter().enumerate().all(|(i, kw)| self.is_keyword_ahead(i + 4, &[*kw]))
1110 })
1111 {
1112 return true;
1113 }
1114 SUFFIXES.iter().any(|suffix| {
1116 suffix.iter().enumerate().all(|(i, kw)| {
1117 self.tree_look_ahead(i + 2, |t| {
1118 if let TokenTree::Token(token, _) = t {
1119 token.is_keyword(*kw)
1120 } else {
1121 false
1122 }
1123 })
1124 .unwrap_or(false)
1125 })
1126 })
1127 } else {
1128 SUFFIXES.iter().any(|suffix| {
1129 suffix.iter().enumerate().all(|(i, kw)| {
1130 if i == 0 {
1132 match *kw {
1133 kw::Const => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)),
1134 kw::Unsafe => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe)),
1135 kw::Auto => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Auto,
token_type: crate::parser::token_type::TokenType::KwAuto,
}exp!(Auto)),
1136 kw::Trait => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait)),
1137 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1138 }
1139 } else {
1140 self.is_keyword_ahead(i, &[*kw])
1141 }
1142 })
1143 })
1144 }
1145 }
1146
1147 fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
1149 let impl_restriction = self.parse_impl_restriction()?;
1150 let constness = self.parse_constness(Case::Sensitive);
1151 if let Const::Yes(span) = constness {
1152 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1153 }
1154 let safety = self.parse_safety(Case::Sensitive);
1155 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)) {
1157 self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
1158 IsAuto::Yes
1159 } else {
1160 IsAuto::No
1161 };
1162
1163 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait))?;
1164 let ident = self.parse_ident()?;
1165 let mut generics = self.parse_generics()?;
1166
1167 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));
1169 let span_at_colon = self.prev_token.span;
1170 let bounds = if had_colon { self.parse_generic_bounds()? } else { ThinVec::new() };
1171
1172 let span_before_eq = self.prev_token.span;
1173 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1174 if had_colon {
1176 let span = span_at_colon.to(span_before_eq);
1177 self.dcx().emit_err(diagnostics::BoundsNotAllowedOnTraitAliases { span });
1178 }
1179
1180 let bounds = self.parse_generic_bounds()?;
1181 generics.where_clause = self.parse_where_clause()?;
1182 self.expect_semi()?;
1183
1184 let whole_span = lo.to(self.prev_token.span);
1185 if is_auto == IsAuto::Yes {
1186 self.dcx().emit_err(diagnostics::TraitAliasCannotBeAuto { span: whole_span });
1187 }
1188 if let Safety::Unsafe(_) = safety {
1189 self.dcx().emit_err(diagnostics::TraitAliasCannotBeUnsafe { span: whole_span });
1190 }
1191 if let RestrictionKind::Restricted { .. } = impl_restriction.kind {
1192 self.dcx()
1193 .emit_err(diagnostics::TraitAliasCannotBeImplRestricted { span: whole_span });
1194 }
1195
1196 self.psess.gated_spans.gate(sym::trait_alias, whole_span);
1197
1198 Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
1199 } else {
1200 generics.where_clause = self.parse_where_clause()?;
1202 let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
1203 Ok(ItemKind::Trait(Box::new(Trait {
1204 impl_restriction,
1205 constness,
1206 is_auto,
1207 safety,
1208 ident,
1209 generics,
1210 bounds,
1211 items,
1212 })))
1213 }
1214 }
1215
1216 pub fn parse_impl_item(
1217 &mut self,
1218 force_collect: ForceCollect,
1219 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1220 let fn_parse_mode =
1221 FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
1222 self.parse_assoc_item(fn_parse_mode, force_collect)
1223 }
1224
1225 pub fn parse_trait_item(
1226 &mut self,
1227 force_collect: ForceCollect,
1228 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1229 let fn_parse_mode = FnParseMode {
1230 req_name: |edition, _| edition >= Edition::Edition2018,
1231 context: FnContext::Trait,
1232 req_body: false,
1233 };
1234 self.parse_assoc_item(fn_parse_mode, force_collect)
1235 }
1236
1237 fn parse_assoc_item(
1239 &mut self,
1240 fn_parse_mode: FnParseMode,
1241 force_collect: ForceCollect,
1242 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1243 Ok(self
1244 .parse_item_(
1245 fn_parse_mode,
1246 force_collect,
1247 AllowConstBlockItems::DoesNotMatter, )?
1249 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1250 let kind = match AssocItemKind::try_from(kind) {
1251 Ok(kind) => kind,
1252 Err(kind) => match kind {
1253 ItemKind::Static(StaticItem {
1254 ident,
1255 ty,
1256 safety: _,
1257 mutability: _,
1258 expr,
1259 define_opaque,
1260 eii_impls: _,
1261 }) => {
1262 self.dcx()
1263 .emit_err(diagnostics::AssociatedStaticItemNotAllowed { span });
1264 AssocItemKind::Const(Box::new(ConstItem {
1265 defaultness: Defaultness::Implicit,
1266 ident,
1267 generics: Generics::default(),
1268 ty,
1269 body: expr,
1270 kind: ConstItemKind::Body,
1271 define_opaque,
1272 }))
1273 }
1274 _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
1275 },
1276 };
1277 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1278 }))
1279 }
1280
1281 fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
1287 let ident = self.parse_ident()?;
1288 let mut generics = self.parse_generics()?;
1289
1290 let bounds =
1292 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 { ThinVec::new() };
1293 generics.where_clause = self.parse_where_clause()?;
1294
1295 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 };
1296
1297 let after_where_clause = self.parse_where_clause()?;
1298
1299 self.expect_semi()?;
1300
1301 Ok(ItemKind::TyAlias(Box::new(TyAlias {
1302 defaultness,
1303 ident,
1304 generics,
1305 after_where_clause,
1306 bounds,
1307 ty,
1308 })))
1309 }
1310
1311 fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
1321 let lo = self.token.span;
1322
1323 let mut prefix = ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo() };
1324 let kind =
1325 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() {
1326 let mod_sep_ctxt = self.token.span.ctxt();
1328 if self.eat_path_sep() {
1329 prefix
1330 .segments
1331 .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
1332 }
1333
1334 self.parse_use_tree_glob_or_nested()?
1335 } else {
1336 prefix = self.parse_path(PathStyle::Mod)?;
1338
1339 if self.eat_path_sep() {
1340 self.parse_use_tree_glob_or_nested()?
1341 } else {
1342 while self.eat_noexpect(&token::Colon) {
1344 self.dcx().emit_err(diagnostics::SingleColonImportPath {
1345 span: self.prev_token.span,
1346 });
1347
1348 self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
1350 prefix.span = lo.to(self.prev_token.span);
1351 }
1352
1353 UseTreeKind::Simple(self.parse_rename()?)
1354 }
1355 };
1356
1357 Ok(UseTree { prefix, kind })
1358 }
1359
1360 fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
1362 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
1363 UseTreeKind::Glob(self.prev_token.span)
1364 } else {
1365 let lo = self.token.span;
1366 UseTreeKind::Nested {
1367 items: self.parse_use_tree_list()?,
1368 span: lo.to(self.prev_token.span),
1369 }
1370 })
1371 }
1372
1373 fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
1379 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| {
1380 p.recover_vcs_conflict_marker();
1381 Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
1382 })
1383 .map(|(r, _)| r)
1384 }
1385
1386 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1387 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)) {
1388 self.parse_ident_or_underscore().map(Some)
1389 } else {
1390 Ok(None)
1391 }
1392 }
1393
1394 fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
1395 match self.token.ident() {
1396 Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
1397 self.bump();
1398 Ok(ident)
1399 }
1400 _ => self.parse_ident(),
1401 }
1402 }
1403
1404 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1413 let orig_ident = self.parse_crate_name_with_dashes()?;
1415 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1416 (Some(orig_ident.name), rename)
1417 } else {
1418 (None, orig_ident)
1419 };
1420 self.expect_semi()?;
1421 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1422 }
1423
1424 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1425 let ident = if self.token.is_keyword(kw::SelfLower) {
1426 self.parse_path_segment_ident()
1427 } else {
1428 self.parse_ident()
1429 }?;
1430
1431 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1432 if self.token != dash.tok {
1433 return Ok(ident);
1434 }
1435
1436 let mut dashes = ::alloc::vec::Vec::new()vec![];
1438 let mut idents = ::alloc::vec::Vec::new()vec![];
1439 while self.eat(dash) {
1440 dashes.push(self.prev_token.span);
1441 idents.push(self.parse_ident()?);
1442 }
1443
1444 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1445 let mut fixed_name = ident.name.to_string();
1446 for part in idents {
1447 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1448 }
1449
1450 self.dcx().emit_err(diagnostics::ExternCrateNameWithDashes {
1451 span: fixed_name_sp,
1452 sugg: diagnostics::ExternCrateNameWithDashesSugg { dashes },
1453 });
1454
1455 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1456 }
1457
1458 fn parse_item_foreign_mod(
1469 &mut self,
1470 attrs: &mut AttrVec,
1471 mut safety: Safety,
1472 ) -> PResult<'a, ItemKind> {
1473 let extern_span = self.prev_token_uninterpolated_span();
1474 let abi = self.parse_abi(); if safety == Safety::Default
1477 && self.token.is_keyword(kw::Unsafe)
1478 && self.look_ahead(1, |t| *t == token::OpenBrace)
1479 {
1480 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();
1481 safety = Safety::Unsafe(self.token.span);
1482 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));
1483 }
1484 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1485 extern_span,
1486 safety,
1487 abi,
1488 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1489 }))
1490 }
1491
1492 pub fn parse_foreign_item(
1494 &mut self,
1495 force_collect: ForceCollect,
1496 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1497 let fn_parse_mode = FnParseMode {
1498 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1499 context: FnContext::Free,
1500 req_body: false,
1501 };
1502 Ok(self
1503 .parse_item_(
1504 fn_parse_mode,
1505 force_collect,
1506 AllowConstBlockItems::DoesNotMatter, )?
1508 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1509 let kind = match ForeignItemKind::try_from(kind) {
1510 Ok(kind) => kind,
1511 Err(kind) => match kind {
1512 ItemKind::Const(ConstItem { ident, ty, body, .. }) => {
1513 let const_span = Some(span.with_hi(ident.span.lo()))
1514 .filter(|span| span.can_be_used_for_suggestions());
1515 self.dcx().emit_err(diagnostics::ExternItemCannotBeConst {
1516 ident_span: ident.span,
1517 const_span,
1518 });
1519 ForeignItemKind::Static(Box::new(StaticItem {
1520 ident,
1521 ty,
1522 mutability: Mutability::Not,
1523 expr: body,
1524 safety: Safety::Default,
1525 define_opaque: None,
1526 eii_impls: ThinVec::default(),
1527 }))
1528 }
1529 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1530 },
1531 };
1532 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1533 }))
1534 }
1535
1536 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1537 let span = self.psess.source_map().guess_head_span(span);
1539 let descr = kind.descr();
1540 let help = match kind {
1541 ItemKind::DelegationMac(DelegationMac {
1542 suffixes: DelegationSuffixes::Glob(_),
1543 ..
1544 }) => false,
1545 _ => true,
1546 };
1547 self.dcx().emit_err(diagnostics::BadItemKind { span, descr, ctx, help });
1548 None
1549 }
1550
1551 fn is_use_closure(&self) -> bool {
1552 if self.token.is_keyword(kw::Use) {
1553 self.look_ahead(1, |token| {
1555 let dist =
1557 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1558
1559 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))
1560 })
1561 } else {
1562 false
1563 }
1564 }
1565
1566 fn is_unsafe_foreign_mod(&self) -> bool {
1567 if !self.token.is_keyword(kw::Unsafe) {
1569 return false;
1570 }
1571 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1573 return false;
1574 }
1575
1576 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1578
1579 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, _)))
1584 == Some(true)
1585 }
1586
1587 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1588 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) {
1589 !self.look_ahead(1, |token| {
1591 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1592 return true;
1593 }
1594 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1595 })
1596 } else {
1597 (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)
1599 || 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))
1600 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1601 };
1602
1603 if is_global_static {
1604 let safety = self.parse_safety(case);
1605 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);
1606 Some(safety)
1607 } else {
1608 None
1609 }
1610 }
1611
1612 fn recover_const_mut(&mut self, const_span: Span) {
1614 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)) {
1615 let span = self.prev_token.span;
1616 self.dcx()
1617 .emit_err(diagnostics::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1618 } 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)) {
1619 let span = self.prev_token.span;
1620 self.dcx()
1621 .emit_err(diagnostics::ConstLetMutuallyExclusive { span: const_span.to(span) });
1622 }
1623 }
1624
1625 fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
1626 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1627 let const_span = self.prev_token.span;
1628 self.psess.gated_spans.gate(sym::const_block_items, const_span);
1629 let block = self.parse_block()?;
1630 Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
1631 }
1632
1633 fn parse_static_item(
1640 &mut self,
1641 safety: Safety,
1642 mutability: Mutability,
1643 ) -> PResult<'a, ItemKind> {
1644 let ident = self.parse_ident()?;
1645
1646 if self.token == TokenKind::Lt && self.may_recover() {
1647 let generics = self.parse_generics()?;
1648 self.dcx().emit_err(diagnostics::StaticWithGenerics { span: generics.span });
1649 }
1650
1651 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))) {
1654 (true, false) => self.parse_ty()?,
1655 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1658 };
1659
1660 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 };
1661
1662 self.expect_semi()?;
1663
1664 let item = StaticItem {
1665 ident,
1666 ty,
1667 safety,
1668 mutability,
1669 expr,
1670 define_opaque: None,
1671 eii_impls: ThinVec::default(),
1672 };
1673 Ok(ItemKind::Static(Box::new(item)))
1674 }
1675
1676 fn parse_const_item(
1685 &mut self,
1686 const_span: Span,
1687 ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<Box<Expr>>)> {
1688 let ident = self.parse_ident_or_underscore()?;
1689
1690 let mut generics = self.parse_generics()?;
1691
1692 if !generics.span.is_empty() {
1695 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1696 }
1697
1698 let ty = match (
1701 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1702 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)),
1703 ) {
1704 (true, false) => self.parse_ty()?,
1705 (colon, _) => self.recover_missing_global_item_type(colon, None),
1707 };
1708
1709 let before_where_clause =
1712 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1713
1714 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)) { Some(self.parse_expr()?) } else { None };
1715
1716 let after_where_clause = self.parse_where_clause()?;
1717
1718 if before_where_clause.has_where_token
1722 && let Some(rhs) = &rhs
1723 {
1724 self.dcx().emit_err(diagnostics::WhereClauseBeforeConstBody {
1725 span: before_where_clause.span,
1726 name: ident.span,
1727 body: rhs.span,
1728 sugg: if !after_where_clause.has_where_token {
1729 self.psess.source_map().span_to_snippet(rhs.span).ok().map(|body_s| {
1730 diagnostics::WhereClauseBeforeConstBodySugg {
1731 left: before_where_clause.span.shrink_to_lo(),
1732 snippet: body_s,
1733 right: before_where_clause.span.shrink_to_hi().to(rhs.span),
1734 }
1735 })
1736 } else {
1737 None
1740 },
1741 });
1742 }
1743
1744 let mut predicates = before_where_clause.predicates;
1751 predicates.extend(after_where_clause.predicates);
1752 let where_clause = WhereClause {
1753 has_where_token: before_where_clause.has_where_token
1754 || after_where_clause.has_where_token,
1755 predicates,
1756 span: if after_where_clause.has_where_token {
1757 after_where_clause.span
1758 } else {
1759 before_where_clause.span
1760 },
1761 };
1762
1763 if where_clause.has_where_token {
1764 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1765 }
1766
1767 generics.where_clause = where_clause;
1768
1769 if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
1770 return Ok((ident, generics, ty, Some(rhs)));
1771 }
1772 self.expect_semi()?;
1773
1774 Ok((ident, generics, ty, rhs))
1775 }
1776
1777 fn recover_missing_global_item_type(
1780 &mut self,
1781 colon_present: bool,
1782 m: Option<Mutability>,
1783 ) -> Box<Ty> {
1784 let kind = match m {
1787 Some(Mutability::Mut) => "static mut",
1788 Some(Mutability::Not) => "static",
1789 None => "const",
1790 };
1791
1792 let colon = match colon_present {
1793 true => "",
1794 false => ":",
1795 };
1796
1797 let span = self.prev_token.span.shrink_to_hi();
1798 let err = self.dcx().create_err(diagnostics::MissingConstType { span, colon, kind });
1799 err.stash(span, StashKey::ItemNoType);
1800
1801 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID })
1804 }
1805
1806 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1808 if self.token.is_keyword(kw::Struct) {
1809 let span = self.prev_token.span.to(self.token.span);
1810 let err = diagnostics::EnumStructMutuallyExclusive { span };
1811 if self.look_ahead(1, |t| t.is_ident()) {
1812 self.bump();
1813 self.dcx().emit_err(err);
1814 } else {
1815 return Err(self.dcx().create_err(err));
1816 }
1817 }
1818
1819 let prev_span = self.prev_token.span;
1820 let ident = self.parse_ident()?;
1821 let mut generics = self.parse_generics()?;
1822 generics.where_clause = self.parse_where_clause()?;
1823
1824 let (variants, _) = if self.token == TokenKind::Semi {
1826 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
1827 self.bump();
1828 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1829 } else {
1830 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| {
1831 p.parse_enum_variant(ident.span)
1832 })
1833 .map_err(|mut err| {
1834 err.span_label(ident.span, "while parsing this enum");
1835 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1837 let snapshot = self.create_snapshot_for_diagnostic();
1838 self.bump();
1839 match self.parse_ty() {
1840 Ok(_) => {
1841 err.span_suggestion_verbose(
1842 prev_span,
1843 "perhaps you meant to use `struct` here",
1844 "struct",
1845 Applicability::MaybeIncorrect,
1846 );
1847 }
1848 Err(e) => {
1849 e.cancel();
1850 }
1851 }
1852 self.restore_snapshot(snapshot);
1853 }
1854 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1855 self.bump(); err
1857 })?
1858 };
1859
1860 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1861 Ok(ItemKind::Enum(ident, generics, enum_definition))
1862 }
1863
1864 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1865 self.recover_vcs_conflict_marker();
1866 let variant_attrs = self.parse_outer_attributes()?;
1867 self.recover_vcs_conflict_marker();
1868 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1869 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1870 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1871 let vlo = this.token.span;
1872
1873 let vis = this.parse_visibility(FollowedByType::No)?;
1874 if !this.recover_nested_adt_item(kw::Enum)? {
1875 return Ok((None, Trailing::No, UsePreAttrPos::No));
1876 }
1877 let ident = this.parse_field_ident("enum", vlo)?;
1878
1879 if this.token == token::Bang {
1880 if let Err(err) = this.unexpected() {
1881 err.with_note(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("macros cannot expand to enum variants"))msg!("macros cannot expand to enum variants")).emit();
1882 }
1883
1884 this.bump();
1885 this.parse_delim_args()?;
1886
1887 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1888 }
1889
1890 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)) {
1891 let (fields, recovered) =
1893 match this.parse_record_struct_body("struct", ident.span, false) {
1894 Ok((fields, recovered)) => (fields, recovered),
1895 Err(mut err) => {
1896 if this.token == token::Colon {
1897 return Err(err);
1899 }
1900 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1901 this.bump(); err.span_label(span, "while parsing this enum");
1903 err.help(help);
1904 let guar = err.emit();
1905 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1906 }
1907 };
1908 VariantData::Struct { fields, recovered }
1909 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1910 let body = match this.parse_tuple_struct_body() {
1911 Ok(body) => body,
1912 Err(mut err) => {
1913 if this.token == token::Colon {
1914 return Err(err);
1916 }
1917 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
1918 this.bump(); err.span_label(span, "while parsing this enum");
1920 err.help(help);
1921 err.emit();
1922 ::thin_vec::ThinVec::new()thin_vec![]
1923 }
1924 };
1925 VariantData::Tuple(body, DUMMY_NODE_ID)
1926 } else {
1927 VariantData::Unit(DUMMY_NODE_ID)
1928 };
1929
1930 let disr_expr =
1931 if this.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) { Some(this.parse_expr_anon_const()?) } else { None };
1932
1933 let span = vlo.to(this.prev_token.span);
1934 if ident.name == kw::Underscore {
1935 this.psess.gated_spans.gate(sym::unnamed_enum_variants, span);
1936 }
1937 let vr = ast::Variant {
1938 ident,
1939 vis,
1940 id: DUMMY_NODE_ID,
1941 attrs: variant_attrs,
1942 data: struct_def,
1943 disr_expr,
1944 span,
1945 is_placeholder: false,
1946 };
1947
1948 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
1949 })
1950 .map_err(|mut err| {
1951 err.help(help);
1952 err
1953 })
1954 }
1955
1956 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
1958 let ident = self.parse_ident()?;
1959
1960 let mut generics = self.parse_generics()?;
1961
1962 let vdata = if self.token.is_keyword(kw::Where) {
1977 let tuple_struct_body;
1978 (generics.where_clause, tuple_struct_body) =
1979 self.parse_struct_where_clause(ident, generics.span)?;
1980
1981 if let Some(body) = tuple_struct_body {
1982 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
1984 self.expect_semi()?;
1985 body
1986 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1987 VariantData::Unit(DUMMY_NODE_ID)
1989 } else {
1990 let (fields, recovered) = self.parse_record_struct_body(
1992 "struct",
1993 ident.span,
1994 generics.where_clause.has_where_token,
1995 )?;
1996 VariantData::Struct { fields, recovered }
1997 }
1998 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
2000 VariantData::Unit(DUMMY_NODE_ID)
2001 } else if self.token == token::OpenBrace {
2003 let (fields, recovered) = self.parse_record_struct_body(
2004 "struct",
2005 ident.span,
2006 generics.where_clause.has_where_token,
2007 )?;
2008 VariantData::Struct { fields, recovered }
2009 } else if self.token == token::OpenParen {
2011 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
2012 generics.where_clause = self.parse_where_clause()?;
2013 self.expect_semi()?;
2014 body
2015 } else {
2016 let err = diagnostics::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
2017 return Err(self.dcx().create_err(err));
2018 };
2019
2020 Ok(ItemKind::Struct(ident, generics, vdata))
2021 }
2022
2023 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
2025 let ident = self.parse_ident()?;
2026
2027 let mut generics = self.parse_generics()?;
2028
2029 let vdata = if self.token.is_keyword(kw::Where) {
2030 generics.where_clause = self.parse_where_clause()?;
2031 let (fields, recovered) = self.parse_record_struct_body(
2032 "union",
2033 ident.span,
2034 generics.where_clause.has_where_token,
2035 )?;
2036 VariantData::Struct { fields, recovered }
2037 } else if self.token == token::OpenBrace {
2038 let (fields, recovered) = self.parse_record_struct_body(
2039 "union",
2040 ident.span,
2041 generics.where_clause.has_where_token,
2042 )?;
2043 VariantData::Struct { fields, recovered }
2044 } else {
2045 let token_str = super::token_descr(&self.token);
2046 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}");
2047 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2048 err.span_label(self.token.span, "expected `where` or `{` after union name");
2049 return Err(err);
2050 };
2051
2052 Ok(ItemKind::Union(ident, generics, vdata))
2053 }
2054
2055 pub(crate) fn parse_record_struct_body(
2060 &mut self,
2061 adt_ty: &str,
2062 ident_span: Span,
2063 parsed_where: bool,
2064 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
2065 let mut fields = ThinVec::new();
2066 let mut recovered = Recovered::No;
2067 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2068 while self.token != token::CloseBrace {
2069 match self.parse_field_def(adt_ty, ident_span) {
2070 Ok(field) => {
2071 fields.push(field);
2072 }
2073 Err(mut err) => {
2074 self.consume_block(
2075 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
2076 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
2077 ConsumeClosingDelim::No,
2078 );
2079 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}"));
2080 let guar = err.emit();
2081 recovered = Recovered::Yes(guar);
2082 break;
2083 }
2084 }
2085 }
2086 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
2087 } else {
2088 let token_str = super::token_descr(&self.token);
2089 let where_str = if parsed_where { "" } else { "`where`, or " };
2090 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}");
2091 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2092 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",));
2093 return Err(err);
2094 }
2095
2096 Ok((fields, recovered))
2097 }
2098
2099 fn parse_unsafe_field(&mut self) -> Safety {
2100 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)) {
2102 let span = self.prev_token.span;
2103 self.psess.gated_spans.gate(sym::unsafe_fields, span);
2104 Safety::Unsafe(span)
2105 } else {
2106 Safety::Default
2107 }
2108 }
2109 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
2112 let openparen_span = self.token.span;
2113 let mut encountered_colon = false;
2114 self.parse_paren_comma_seq(|p| {
2115 let attrs = p.parse_outer_attributes()?;
2116 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
2117 let mut snapshot = None;
2118 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
2119 snapshot = Some(p.create_snapshot_for_diagnostic());
2123 }
2124 let lo = p.token.span;
2125 let vis = match p.parse_visibility(FollowedByType::Yes) {
2126 Ok(vis) => vis,
2127 Err(err) => {
2128 if let Some(ref mut snapshot) = snapshot {
2129 snapshot.recover_vcs_conflict_marker();
2130 }
2131 return Err(err);
2132 }
2133 };
2134 let mut_restriction = p.parse_mut_restriction()?;
2135 encountered_colon |=
2136 p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
2137 let ty = match p.parse_ty() {
2140 Ok(ty) => ty,
2141 Err(err) => {
2142 if let Some(ref mut snapshot) = snapshot {
2143 snapshot.recover_vcs_conflict_marker();
2144 }
2145 return Err(err);
2146 }
2147 };
2148 let mut default = None;
2149 if p.token == token::Eq {
2150 let mut snapshot = p.create_snapshot_for_diagnostic();
2151 snapshot.bump();
2152 match snapshot.parse_expr_anon_const() {
2153 Ok(const_expr) => {
2154 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2155 p.psess.gated_spans.gate(sym::default_field_values, sp);
2156 p.restore_snapshot(snapshot);
2157 default = Some(const_expr);
2158 }
2159 Err(err) => {
2160 err.cancel();
2161 }
2162 }
2163 }
2164
2165 Ok((
2166 FieldDef {
2167 span: lo.to(ty.span),
2168 vis,
2169 extras: Self::field_def_extras(Safety::Default, mut_restriction, default),
2170 ident: None,
2171 id: DUMMY_NODE_ID,
2172 ty,
2173 attrs,
2174 is_placeholder: false,
2175 },
2176 Trailing::from(p.token == token::Comma),
2177 UsePreAttrPos::No,
2178 ))
2179 })
2180 })
2181 .map(|(r, _)| r)
2182 .map_err(|mut error| {
2183 if self.token == token::Colon {
2184 error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
2185 }
2186 if encountered_colon {
2187 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
2188 self.bump();
2189 error.subdiagnostic(UseRegularStructSuggestion {
2190 open: openparen_span,
2191 close: self.prev_token.span,
2192 semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
2193 });
2194 }
2195 error
2196 })
2197 }
2198
2199 fn field_def_extras(
2200 safety: Safety,
2201 mut_restriction: MutRestriction,
2202 default: Option<AnonConst>,
2203 ) -> Option<Box<FieldDefExtras>> {
2204 match (safety, mut_restriction, default) {
2205 (
2206 Safety::Default,
2207 MutRestriction { kind: RestrictionKind::Unrestricted, span: _ },
2210 None,
2211 ) => None,
2212 (safety, mut_restriction, default) => {
2213 Some(Box::new(FieldDefExtras { safety, mut_restriction, default }))
2214 }
2215 }
2216 }
2217
2218 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2220 self.recover_vcs_conflict_marker();
2221 let attrs = self.parse_outer_attributes()?;
2222 self.recover_vcs_conflict_marker();
2223 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2224 let lo = this.token.span;
2225 let vis = this.parse_visibility(FollowedByType::No)?;
2226 let mut_restriction = this.parse_mut_restriction()?;
2227 let safety = this.parse_unsafe_field();
2228 this.parse_single_struct_field(
2229 adt_ty,
2230 lo,
2231 vis,
2232 mut_restriction,
2233 safety,
2234 attrs,
2235 ident_span,
2236 )
2237 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2238 })
2239 }
2240
2241 fn parse_single_struct_field(
2243 &mut self,
2244 adt_ty: &str,
2245 lo: Span,
2246 vis: Visibility,
2247 mut_restriction: MutRestriction,
2248 safety: Safety,
2249 attrs: AttrVec,
2250 ident_span: Span,
2251 ) -> PResult<'a, FieldDef> {
2252 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, mut_restriction, safety, attrs)?;
2253 match self.token.kind {
2254 token::Comma => {
2255 self.bump();
2256 }
2257 token::Semi => {
2258 self.bump();
2259 let sp = self.prev_token.span;
2260 let mut err =
2261 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 `,`"));
2262 err.span_suggestion_short(
2263 sp,
2264 "replace `;` with `,`",
2265 ",",
2266 Applicability::MachineApplicable,
2267 );
2268 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}"));
2269 err.emit();
2270 }
2271 token::CloseBrace => {}
2272 token::DocComment(..) => {
2273 let previous_span = self.prev_token.span;
2274 let mut err = diagnostics::DocCommentDoesNotDocumentAnything {
2275 span: self.token.span,
2276 missing_comma: None,
2277 };
2278 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 {
2280 self.dcx().emit_err(err);
2281 } else {
2282 let sp = previous_span.shrink_to_hi();
2283 err.missing_comma = Some(sp);
2284 return Err(self.dcx().create_err(err));
2285 }
2286 }
2287 _ => {
2288 let sp = self.prev_token.span.shrink_to_hi();
2289 let msg =
2290 ::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));
2291
2292 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2294 && let Some(last_segment) = segments.last()
2295 {
2296 let guar = self.check_trailing_angle_brackets(
2297 last_segment,
2298 &[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)],
2299 );
2300 if let Some(_guar) = guar {
2301 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2304
2305 return Ok(a_var);
2308 }
2309 }
2310
2311 let mut err = self.dcx().struct_span_err(sp, msg);
2312
2313 if self.token.is_ident()
2314 || (self.token == TokenKind::Pound
2315 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2316 {
2317 err.span_suggestion(
2320 sp,
2321 "try adding a comma",
2322 ",",
2323 Applicability::MachineApplicable,
2324 );
2325 err.emit();
2326 } else {
2327 return Err(err);
2328 }
2329 }
2330 }
2331 Ok(a_var)
2332 }
2333
2334 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2335 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)) {
2336 let sm = self.psess.source_map();
2337 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2338 let semi_typo = self.token == token::Semi
2339 && self.look_ahead(1, |t| {
2340 t.is_path_start()
2341 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2344 (Ok(l), Ok(r)) => l.line == r.line,
2345 _ => true,
2346 }
2347 });
2348 if eq_typo || semi_typo {
2349 self.bump();
2350 err.with_span_suggestion_short(
2352 self.prev_token.span,
2353 "field names and their types are separated with `:`",
2354 ":",
2355 Applicability::MachineApplicable,
2356 )
2357 .emit();
2358 } else {
2359 return Err(err);
2360 }
2361 }
2362 Ok(())
2363 }
2364
2365 fn parse_name_and_ty(
2367 &mut self,
2368 adt_ty: &str,
2369 lo: Span,
2370 vis: Visibility,
2371 mut_restriction: MutRestriction,
2372 safety: Safety,
2373 attrs: AttrVec,
2374 ) -> PResult<'a, FieldDef> {
2375 let name = self.parse_field_ident(adt_ty, lo)?;
2376 if self.token == token::Bang {
2377 if let Err(mut err) = self.unexpected() {
2378 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2380 return Err(err);
2381 }
2382 }
2383 self.expect_field_ty_separator()?;
2384 let ty = self.parse_ty()?;
2385 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2386 self.dcx()
2387 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2388 .with_span_suggestion_verbose(
2389 self.token.span,
2390 "write a path separator here",
2391 "::",
2392 Applicability::MaybeIncorrect,
2393 )
2394 .emit();
2395 }
2396 let default = if self.token == token::Eq {
2397 self.bump();
2398 let const_expr = self.parse_expr_anon_const()?;
2399 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2400 self.psess.gated_spans.gate(sym::default_field_values, sp);
2401 Some(const_expr)
2402 } else {
2403 None
2404 };
2405 Ok(FieldDef {
2406 span: lo.to(self.prev_token.span),
2407 ident: Some(name),
2408 vis,
2409 extras: Self::field_def_extras(safety, mut_restriction, default),
2410 id: DUMMY_NODE_ID,
2411 ty,
2412 attrs,
2413 is_placeholder: false,
2414 })
2415 }
2416
2417 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2420 let (ident, is_raw) = self.ident_or_err(true)?;
2421 if is_raw == IdentIsRaw::No
2422 && ident.is_reserved()
2423 && !(ident.name == kw::Underscore && adt_ty == "enum")
2424 {
2425 let snapshot = self.create_snapshot_for_diagnostic();
2426 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2427 let inherited_vis = Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited };
2428 let fn_parse_mode =
2430 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2431 match self.parse_fn(
2432 &mut AttrVec::new(),
2433 fn_parse_mode,
2434 lo,
2435 &inherited_vis,
2436 Case::Insensitive,
2437 ) {
2438 Ok(_) => {
2439 self.dcx().struct_span_err(
2440 lo.to(self.prev_token.span),
2441 ::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"),
2442 )
2443 .with_help(
2444 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2445 )
2446 .with_help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information")
2447 }
2448 Err(err) => {
2449 err.cancel();
2450 self.restore_snapshot(snapshot);
2451 self.expected_ident_found_err()
2452 }
2453 }
2454 } 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)) {
2455 match self.parse_item_struct() {
2456 Ok(item) => {
2457 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2458 self.dcx()
2459 .struct_span_err(
2460 lo.with_hi(ident.span.hi()),
2461 ::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"),
2462 )
2463 .with_help(
2464 "consider creating a new `struct` definition instead of nesting",
2465 )
2466 }
2467 Err(err) => {
2468 err.cancel();
2469 self.restore_snapshot(snapshot);
2470 self.expected_ident_found_err()
2471 }
2472 }
2473 } else {
2474 let mut err = self.expected_ident_found_err();
2475 if self.eat_keyword_noexpect(kw::Let)
2476 && let removal_span = self.prev_token.span.until(self.token.span)
2477 && let Ok(ident) = self
2478 .parse_ident_common(false)
2479 .map_err(|err| err.cancel())
2481 && self.token == TokenKind::Colon
2482 {
2483 err.span_suggestion(
2484 removal_span,
2485 "remove this `let` keyword",
2486 String::new(),
2487 Applicability::MachineApplicable,
2488 );
2489 err.note("the `let` keyword is not allowed in `struct` fields");
2490 err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
2491 err.emit();
2492 return Ok(ident);
2493 } else {
2494 self.restore_snapshot(snapshot);
2495 }
2496 err
2497 };
2498 return Err(err);
2499 }
2500 self.bump();
2501 Ok(ident)
2502 }
2503
2504 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2512 let ident = self.parse_ident()?;
2513 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)) {
2514 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)) {
2516 let params = self.parse_token_tree(); let pspan = params.span();
2518 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2519 self.unexpected()?;
2520 }
2521 let body = self.parse_token_tree(); let bspan = body.span();
2524 let arrow = TokenTree::token_alone(token::FatArrow, pspan.between(bspan)); let tokens = TokenStream::new(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[params, arrow, body]))vec![params, arrow, body]);
2526 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2527 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2528 } else {
2529 self.unexpected_any()?
2530 };
2531
2532 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2533 Ok(ItemKind::MacroDef(
2534 ident,
2535 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2536 ))
2537 }
2538
2539 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2541 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)) {
2542 let macro_rules_span = self.token.span;
2543
2544 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2545 return IsMacroRulesItem::Yes { has_bang: true };
2546 } else if self.look_ahead(1, |t| t.is_ident()) {
2547 self.dcx().emit_err(diagnostics::MacroRulesMissingBang {
2549 span: macro_rules_span,
2550 hi: macro_rules_span.shrink_to_hi(),
2551 });
2552
2553 return IsMacroRulesItem::Yes { has_bang: false };
2554 }
2555 }
2556
2557 IsMacroRulesItem::No
2558 }
2559
2560 fn parse_item_macro_rules(
2562 &mut self,
2563 vis: &Visibility,
2564 has_bang: bool,
2565 ) -> PResult<'a, ItemKind> {
2566 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 {
2569 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2571 let ident = self.parse_ident()?;
2572
2573 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2574 let span = self.prev_token.span;
2576 self.dcx().emit_err(diagnostics::MacroNameRemoveBang { span });
2577 }
2578
2579 let body = self.parse_delim_args()?;
2580 self.eat_semi_for_macro_if_needed(&body, None);
2581 self.complain_if_pub_macro(vis, true);
2582
2583 Ok(ItemKind::MacroDef(
2584 ident,
2585 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2586 ))
2587 }
2588
2589 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2592 if let VisibilityKind::Inherited = vis.kind {
2593 return;
2594 }
2595
2596 let vstr = pprust::vis_to_string(vis);
2597 let vstr = vstr.trim_end();
2598 if macro_rules {
2599 self.dcx().emit_err(diagnostics::MacroRulesVisibility { span: vis.span, vis: vstr });
2600 } else {
2601 self.dcx()
2602 .emit_err(diagnostics::MacroInvocationVisibility { span: vis.span, vis: vstr });
2603 }
2604 }
2605
2606 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
2607 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)) {
2608 self.report_invalid_macro_expansion_item(args, path);
2609 }
2610 }
2611
2612 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
2613 let span = args.dspan.entire();
2614 let mut err = self.dcx().struct_span_err(
2615 span,
2616 "macros that expand to items must be delimited with braces or followed by a semicolon",
2617 );
2618 if !span.from_expansion() {
2621 let DelimSpan { open, close } = args.dspan;
2622 if let Some(path) = path
2625 && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2626 && args.delim == Delimiter::Parenthesis
2627 {
2628 let replace =
2629 if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2630 err.multipart_suggestion(
2631 "to define a macro, remove the parentheses around the macro name",
2632 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(open, replace.to_string()), (close, String::new())]))vec![(open, replace.to_string()), (close, String::new())],
2633 Applicability::MachineApplicable,
2634 );
2635 } else {
2636 err.multipart_suggestion(
2637 "change the delimiters to curly braces",
2638 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(open, "{".to_string()), (close, '}'.to_string())]))vec![(open, "{".to_string()), (close, '}'.to_string())],
2639 Applicability::MaybeIncorrect,
2640 );
2641 err.span_suggestion(
2642 span.with_neighbor(self.token.span).shrink_to_hi(),
2643 "add a semicolon",
2644 ';',
2645 Applicability::MaybeIncorrect,
2646 );
2647 }
2648 }
2649 err.emit();
2650 }
2651
2652 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2655 if (self.token.is_keyword(kw::Enum)
2656 || self.token.is_keyword(kw::Struct)
2657 || self.token.is_keyword(kw::Union))
2658 && self.look_ahead(1, |t| t.is_ident())
2659 {
2660 let kw_token = self.token;
2661 let kw_str = pprust::token_to_string(&kw_token);
2662 let item = self.parse_item(
2663 ForceCollect::No,
2664 AllowConstBlockItems::DoesNotMatter, )?;
2666 let mut item = item.unwrap().span;
2667 if self.token == token::Comma {
2668 item = item.to(self.token.span);
2669 }
2670 self.dcx().emit_err(diagnostics::NestedAdt {
2671 span: kw_token.span,
2672 item,
2673 kw_str,
2674 keyword: keyword.as_str(),
2675 });
2676 return Ok(false);
2678 }
2679 Ok(true)
2680 }
2681}
2682
2683type ReqName = fn(Edition, IsDotDotDot) -> bool;
2692
2693#[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)]
2694pub(crate) enum IsDotDotDot {
2695 Yes,
2696 No,
2697}
2698
2699#[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)]
2707pub(crate) struct FnParseMode {
2708 pub(super) req_name: ReqName,
2734 pub(super) context: FnContext,
2737 pub(super) req_body: bool,
2756}
2757
2758#[derive(#[automatically_derived]
impl ::core::clone::Clone for FnContext {
#[inline]
fn clone(&self) -> FnContext { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FnContext { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for FnContext {
#[inline]
fn eq(&self, other: &FnContext) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FnContext {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
2761pub(crate) enum FnContext {
2762 Free,
2764 Trait,
2766 Impl,
2768}
2769
2770impl<'a> Parser<'a> {
2772 fn parse_fn(
2774 &mut self,
2775 attrs: &mut AttrVec,
2776 fn_parse_mode: FnParseMode,
2777 sig_lo: Span,
2778 vis: &Visibility,
2779 case: Case,
2780 ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
2781 let fn_span = self.token.span;
2782 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)
2786 {
2787 Ok(decl) => decl,
2788 Err(old_err) => {
2789 if self.token.is_keyword(kw::For) {
2791 old_err.cancel();
2792 return Err(self.dcx().create_err(diagnostics::FnTypoWithImpl { fn_span }));
2793 } else {
2794 return Err(old_err);
2795 }
2796 }
2797 };
2798
2799 let fn_params_end = self.prev_token.span.shrink_to_hi();
2802
2803 let contract = self.parse_contract()?;
2804
2805 generics.where_clause = self.parse_where_clause()?; let fn_params_end =
2809 if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
2810
2811 let mut sig_hi = self.prev_token.span;
2812 let body =
2814 self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
2815 let fn_sig_span = sig_lo.to(sig_hi);
2816 Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
2817 }
2818
2819 fn error_fn_body_not_found(
2821 &mut self,
2822 ident_span: Span,
2823 req_body: bool,
2824 fn_params_end: Option<Span>,
2825 ) -> PResult<'a, ErrorGuaranteed> {
2826 let expected: &[_] =
2827 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)] };
2828 match self.expected_one_of_not_found(&[], expected) {
2829 Ok(error_guaranteed) => Ok(error_guaranteed),
2830 Err(mut err) => {
2831 if self.token == token::CloseBrace {
2832 err.span_label(ident_span, "while parsing this `fn`");
2835 Ok(err.emit())
2836 } else if self.token == token::RArrow
2837 && let Some(fn_params_end) = fn_params_end
2838 {
2839 let fn_trait_span =
2845 [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
2846 if self.prev_token.is_ident_named(symbol) {
2847 Some(self.prev_token.span)
2848 } else {
2849 None
2850 }
2851 });
2852
2853 let arrow_span = self.token.span;
2858 let ty_span = match self.parse_ret_ty(
2859 AllowPlus::Yes,
2860 RecoverQPath::Yes,
2861 RecoverReturnSign::Yes,
2862 ) {
2863 Ok(ty_span) => ty_span.span().shrink_to_hi(),
2864 Err(parse_error) => {
2865 parse_error.cancel();
2866 return Err(err);
2867 }
2868 };
2869 let ret_ty_span = arrow_span.to(ty_span);
2870
2871 if let Some(fn_trait_span) = fn_trait_span {
2872 err.subdiagnostic(diagnostics::FnTraitMissingParen { span: fn_trait_span });
2875 } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
2876 {
2877 err.primary_message(
2881 "return type should be specified after the function parameters",
2882 );
2883 err.subdiagnostic(diagnostics::MisplacedReturnType {
2884 fn_params_end,
2885 snippet,
2886 ret_ty_span,
2887 });
2888 }
2889 Err(err)
2890 } else {
2891 Err(err)
2892 }
2893 }
2894 }
2895 }
2896
2897 fn parse_fn_body(
2901 &mut self,
2902 attrs: &mut AttrVec,
2903 ident: &Ident,
2904 sig_hi: &mut Span,
2905 req_body: bool,
2906 fn_params_end: Option<Span>,
2907 ) -> PResult<'a, Option<Box<Block>>> {
2908 let has_semi = if req_body {
2909 self.token == TokenKind::Semi
2910 } else {
2911 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))
2913 };
2914 let (inner_attrs, body) = if has_semi {
2915 self.expect_semi()?;
2917 *sig_hi = self.prev_token.span;
2918 (AttrVec::new(), None)
2919 } 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() {
2920 let prev_in_fn_body = self.in_fn_body;
2921 self.in_fn_body = true;
2922 let res = self.parse_block_common(self.token.span, BlockCheckMode::Default, None).map(
2923 |(attrs, mut body)| {
2924 if let Some(guar) = self.fn_body_missing_semi_guar.take() {
2925 body.stmts.push(self.mk_stmt(
2926 body.span,
2927 StmtKind::Expr(self.mk_expr(body.span, ExprKind::Err(guar))),
2928 ));
2929 }
2930 (attrs, Some(body))
2931 },
2932 );
2933 self.in_fn_body = prev_in_fn_body;
2934 res?
2935 } else if self.token == token::Eq {
2936 self.bump(); let eq_sp = self.prev_token.span;
2939 let _ = self.parse_expr()?;
2940 self.expect_semi()?; let span = eq_sp.to(self.prev_token.span);
2942 let guar = self.dcx().emit_err(diagnostics::FunctionBodyEqualsExpr {
2943 span,
2944 sugg: diagnostics::FunctionBodyEqualsExprSugg {
2945 eq: eq_sp,
2946 semi: self.prev_token.span,
2947 },
2948 });
2949 (AttrVec::new(), Some(self.mk_block_err(span, guar)))
2950 } else {
2951 self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
2952 (AttrVec::new(), None)
2953 };
2954 attrs.extend(inner_attrs);
2955 Ok(body)
2956 }
2957
2958 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2959 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2960 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)) {
2963 return true;
2964 }
2965 let mut i = 0;
2966 while i < ALL_QUALS.len() {
2967 let action = self.look_ahead(i + look_ahead, |token| {
2968 if token.is_keyword(kw::Impl) {
2969 return Some(true);
2970 }
2971 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2972 return None;
2974 }
2975 Some(false)
2976 });
2977 if let Some(ret) = action {
2978 return ret;
2979 }
2980 i += 1;
2981 }
2982
2983 self.is_keyword_ahead(i, &[kw::Impl])
2984 }
2985
2986 pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
2991 const ALL_QUALS: &[ExpKeywordPair] = &[
2992 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub),
2993 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen),
2994 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const),
2995 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async),
2996 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe),
2997 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe),
2998 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern),
2999 ];
3000
3001 let quals: &[_] = if check_pub {
3006 ALL_QUALS
3007 } else {
3008 &[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)]
3009 };
3010 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))
3013 && self.look_ahead(1, |t| {
3014 t.is_keyword_case(kw::Fn, case)
3016 || (
3018 (
3019 t.is_non_raw_ident_where(|i|
3020 quals.iter().any(|exp| exp.kw == i.name)
3021 && i.is_reserved()
3023 )
3024 || case == Case::Insensitive
3025 && t.is_non_raw_ident_where(|i| quals.iter().any(|exp| {
3026 exp.kw.as_str() == i.name.as_str().to_lowercase()
3027 }))
3028 )
3029 && !self.is_unsafe_foreign_mod()
3031 && !self.is_async_gen_block()
3033 && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait, kw::Impl])
3035 )
3036 })
3037 || 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)
3039 && self.look_ahead(1, |t| t.can_begin_string_literal())
3043 && (self.tree_look_ahead(2, |tt| {
3044 match tt {
3045 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
3046 TokenTree::Delimited(..) => false,
3047 }
3048 }) == Some(true) ||
3049 (self.may_recover()
3052 && self.tree_look_ahead(2, |tt| {
3053 match tt {
3054 TokenTree::Token(t, _) =>
3055 ALL_QUALS.iter().any(|exp| {
3056 t.is_keyword(exp.kw)
3057 }),
3058 TokenTree::Delimited(..) => false,
3059 }
3060 }) == Some(true)
3061 && self.tree_look_ahead(3, |tt| {
3062 match tt {
3063 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
3064 TokenTree::Delimited(..) => false,
3065 }
3066 }) == Some(true)
3067 )
3068 )
3069 }
3070
3071 pub(super) fn parse_fn_front_matter(
3086 &mut self,
3087 orig_vis: &Visibility,
3088 case: Case,
3089 parsing_mode: FrontMatterParsingMode,
3090 ) -> PResult<'a, FnHeader> {
3091 let sp_start = self.token.span;
3092 let constness = self.parse_constness(case);
3093 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3094 && let Const::Yes(const_span) = constness
3095 {
3096 self.dcx().emit_err(FnPointerCannotBeConst {
3097 span: const_span,
3098 suggestion: const_span.until(self.token.span),
3099 });
3100 }
3101
3102 let async_start_sp = self.token.span;
3103 let coroutine_kind = self.parse_coroutine_kind(case);
3104 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3105 && let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind
3106 {
3107 self.dcx().emit_err(FnPointerCannotBeAsync {
3108 span: async_span,
3109 suggestion: async_span.until(self.token.span),
3110 });
3111 }
3112 let unsafe_start_sp = self.token.span;
3115 let safety = self.parse_safety(case);
3116
3117 let ext_start_sp = self.token.span;
3118 let ext = self.parse_extern(case);
3119
3120 if let Some(CoroutineKind::Async { span, .. }) = coroutine_kind {
3121 if span.is_rust_2015() {
3122 self.dcx().emit_err(diagnostics::AsyncFnIn2015 {
3123 span,
3124 help: diagnostics::HelpUseLatestEdition::new(),
3125 });
3126 }
3127 }
3128
3129 match coroutine_kind {
3130 Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
3131 self.psess.gated_spans.gate(sym::gen_blocks, span);
3132 }
3133 Some(CoroutineKind::Async { .. }) | None => {}
3134 }
3135
3136 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) {
3137 match self.expect_one_of(&[], &[]) {
3141 Ok(Recovered::Yes(_)) => {}
3142 Ok(Recovered::No) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3143 Err(mut err) => {
3144 enum WrongKw {
3146 Duplicated(Span),
3147 Misplaced(Span),
3148 MisplacedDisallowedQualifier,
3153 }
3154
3155 let mut recover_constness = constness;
3157 let mut recover_coroutine_kind = coroutine_kind;
3158 let mut recover_safety = safety;
3159 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)) {
3162 match constness {
3163 Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
3164 Const::No => {
3165 recover_constness = Const::Yes(self.token.span);
3166 match parsing_mode {
3167 FrontMatterParsingMode::Function => {
3168 Some(WrongKw::Misplaced(async_start_sp))
3169 }
3170 FrontMatterParsingMode::FunctionPtrType => {
3171 self.dcx().emit_err(FnPointerCannotBeConst {
3172 span: self.token.span,
3173 suggestion: self
3174 .token
3175 .span
3176 .with_lo(self.prev_token.span.hi()),
3177 });
3178 Some(WrongKw::MisplacedDisallowedQualifier)
3179 }
3180 }
3181 }
3182 }
3183 } 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)) {
3184 match coroutine_kind {
3185 Some(CoroutineKind::Async { span, .. }) => {
3186 Some(WrongKw::Duplicated(span))
3187 }
3188 Some(CoroutineKind::AsyncGen { span, .. }) => {
3189 Some(WrongKw::Duplicated(span))
3190 }
3191 Some(CoroutineKind::Gen { .. }) => {
3192 recover_coroutine_kind = Some(CoroutineKind::AsyncGen {
3193 span: self.token.span,
3194 closure_id: DUMMY_NODE_ID,
3195 return_impl_trait_id: DUMMY_NODE_ID,
3196 });
3197 Some(WrongKw::Misplaced(unsafe_start_sp))
3199 }
3200 None => {
3201 recover_coroutine_kind = Some(CoroutineKind::Async {
3202 span: self.token.span,
3203 closure_id: DUMMY_NODE_ID,
3204 return_impl_trait_id: DUMMY_NODE_ID,
3205 });
3206 match parsing_mode {
3207 FrontMatterParsingMode::Function => {
3208 Some(WrongKw::Misplaced(async_start_sp))
3209 }
3210 FrontMatterParsingMode::FunctionPtrType => {
3211 self.dcx().emit_err(FnPointerCannotBeAsync {
3212 span: self.token.span,
3213 suggestion: self
3214 .token
3215 .span
3216 .with_lo(self.prev_token.span.hi()),
3217 });
3218 Some(WrongKw::MisplacedDisallowedQualifier)
3219 }
3220 }
3221 }
3222 }
3223 } 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)) {
3224 match safety {
3225 Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
3226 Safety::Safe(sp) => {
3227 recover_safety = Safety::Unsafe(self.token.span);
3228 Some(WrongKw::Misplaced(sp))
3229 }
3230 Safety::Default => {
3231 recover_safety = Safety::Unsafe(self.token.span);
3232 Some(WrongKw::Misplaced(ext_start_sp))
3233 }
3234 }
3235 } 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)) {
3236 match safety {
3237 Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
3238 Safety::Unsafe(sp) => {
3239 recover_safety = Safety::Safe(self.token.span);
3240 Some(WrongKw::Misplaced(sp))
3241 }
3242 Safety::Default => {
3243 recover_safety = Safety::Safe(self.token.span);
3244 Some(WrongKw::Misplaced(ext_start_sp))
3245 }
3246 }
3247 } else {
3248 None
3249 };
3250
3251 if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw {
3253 let original_kw = self
3254 .span_to_snippet(original_sp)
3255 .expect("Span extracted directly from keyword should always work");
3256
3257 err.span_suggestion(
3258 self.token_uninterpolated_span(),
3259 ::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"),
3260 "",
3261 Applicability::MachineApplicable,
3262 )
3263 .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"));
3264 }
3265 else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
3267 let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
3268 if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
3269 let misplaced_qual_sp = self.token_uninterpolated_span();
3270 let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
3271
3272 err.span_suggestion(
3273 correct_pos_sp.to(misplaced_qual_sp),
3274 ::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}`"),
3275 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", misplaced_qual,
current_qual))
})format!("{misplaced_qual} {current_qual}"),
3276 Applicability::MachineApplicable,
3277 ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
3278 }
3279 }
3280 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)) {
3282 let sp = sp_start.to(self.prev_token.span);
3283 if let Ok(snippet) = self.span_to_snippet(sp) {
3284 let current_vis = match self.parse_visibility(FollowedByType::No) {
3285 Ok(v) => v,
3286 Err(d) => {
3287 d.cancel();
3288 return Err(err);
3289 }
3290 };
3291 let vs = pprust::vis_to_string(¤t_vis);
3292 let vs = vs.trim_end();
3293
3294 if #[allow(non_exhaustive_omitted_patterns)] match orig_vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(orig_vis.kind, VisibilityKind::Inherited) {
3296 err.span_suggestion(
3297 sp_start.to(self.prev_token.span),
3298 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("visibility `{0}` must come before `{1}`",
vs, snippet))
})format!("visibility `{vs}` must come before `{snippet}`"),
3299 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", vs, snippet))
})format!("{vs} {snippet}"),
3300 Applicability::MachineApplicable,
3301 );
3302 }
3303 else {
3305 err.span_suggestion(
3306 current_vis.span,
3307 "there is already a visibility modifier, remove one",
3308 "",
3309 Applicability::MachineApplicable,
3310 )
3311 .span_note(orig_vis.span, "explicit visibility first seen here");
3312 }
3313 }
3314 }
3315
3316 if let Some(wrong_kw) = wrong_kw
3319 && self.may_recover()
3320 && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
3321 {
3322 self.bump();
3324 self.bump();
3325 if #[allow(non_exhaustive_omitted_patterns)] match wrong_kw {
WrongKw::MisplacedDisallowedQualifier => true,
_ => false,
}matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
3328 err.cancel();
3329 } else {
3330 err.emit();
3331 }
3332 return Ok(FnHeader {
3333 constness: recover_constness,
3334 safety: recover_safety,
3335 coroutine_kind: recover_coroutine_kind,
3336 ext,
3337 });
3338 }
3339
3340 return Err(err);
3341 }
3342 }
3343 }
3344
3345 Ok(FnHeader { constness, safety, coroutine_kind, ext })
3346 }
3347
3348 pub(super) fn parse_fn_decl(
3350 &mut self,
3351 fn_parse_mode: &FnParseMode,
3352 ret_allow_plus: AllowPlus,
3353 recover_return_sign: RecoverReturnSign,
3354 ) -> PResult<'a, Box<FnDecl>> {
3355 Ok(Box::new(FnDecl {
3356 inputs: self.parse_fn_params(fn_parse_mode)?,
3357 output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
3358 }))
3359 }
3360
3361 pub(super) fn parse_fn_params(
3363 &mut self,
3364 fn_parse_mode: &FnParseMode,
3365 ) -> PResult<'a, ThinVec<Param>> {
3366 let mut first_param = true;
3367 if self.token != TokenKind::OpenParen
3369 && !self.token.is_keyword(kw::For)
3371 {
3372 self.dcx().emit_err(diagnostics::MissingFnParams {
3374 span: self.prev_token.span.shrink_to_hi(),
3375 });
3376 return Ok(ThinVec::new());
3377 }
3378
3379 let (mut params, _) = self.parse_paren_comma_seq(|p| {
3380 p.recover_vcs_conflict_marker();
3381 let snapshot = p.create_snapshot_for_diagnostic();
3382 let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| {
3383 let guar = e.emit();
3384 let lo = if let TokenKind::OpenParen = p.prev_token.kind {
3388 p.prev_token.span.shrink_to_hi()
3389 } else {
3390 p.prev_token.span
3391 };
3392 p.restore_snapshot(snapshot);
3393 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)]);
3395 Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
3397 });
3398 first_param = false;
3400 param
3401 })?;
3402 self.deduplicate_recovered_params_names(&mut params);
3404 Ok(params)
3405 }
3406
3407 pub(super) fn parse_param_general(
3412 &mut self,
3413 fn_parse_mode: &FnParseMode,
3414 first_param: bool,
3415 recover_arg_parse: bool,
3416 ) -> PResult<'a, Param> {
3417 let lo = self.token.span;
3418 let attrs = self.parse_outer_attributes()?;
3419 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3420 if let Some(mut param) = this.parse_self_param()? {
3422 param.attrs = attrs;
3423 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
3424 return Ok((res?, Trailing::No, UsePreAttrPos::No));
3425 }
3426
3427 let is_dot_dot_dot = if this.token.kind == token::DotDotDot {
3428 IsDotDotDot::Yes
3429 } else {
3430 IsDotDotDot::No
3431 };
3432 let is_name_required = (fn_parse_mode.req_name)(
3433 this.token.span.with_neighbor(this.prev_token.span).edition(),
3434 is_dot_dot_dot,
3435 );
3436 let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes {
3437 this.psess.buffer_lint(
3438 VARARGS_WITHOUT_PATTERN,
3439 this.token.span,
3440 ast::CRATE_NODE_ID,
3441 diagnostics::VarargsWithoutPattern { span: this.token.span },
3442 );
3443 false
3444 } else {
3445 is_name_required
3446 };
3447 let (pat, ty) = if is_name_required || this.is_named_param() {
3448 {
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:3448",
"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(3448u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("parse_param_general parse_pat (is_name_required:{0})",
is_name_required) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
3449 let (pat, colon) = this.parse_fn_param_pat_colon()?;
3450 if !colon {
3451 let mut err = this.unexpected().unwrap_err();
3452 let pat_span = pat.span;
3453 return if let Some(ident) = this.parameter_without_type(
3454 &mut err,
3455 pat,
3456 is_name_required,
3457 first_param,
3458 fn_parse_mode,
3459 ) {
3460 let guar = err.emit();
3461 let mut arg = dummy_arg(ident, guar);
3462 arg.span = pat_span;
3463 Ok((arg, Trailing::No, UsePreAttrPos::No))
3464 } else {
3465 Err(err)
3466 };
3467 }
3468
3469 this.eat_incorrect_doc_comment_for_param_type();
3470 (pat, this.parse_ty_for_param()?)
3471 } else {
3472 {
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:3472",
"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(3472u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("parse_param_general ident_to_pat")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("parse_param_general ident_to_pat");
3473 let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
3474 this.eat_incorrect_doc_comment_for_param_type();
3475 let mut ty = this.parse_ty_for_param();
3476
3477 if let Ok(t) = &ty {
3478 if let TyKind::Path(_, Path { segments, .. }) = &t.kind
3480 && let Some(segment) = segments.last()
3481 && let Some(guar) =
3482 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)])
3483 {
3484 return Ok((
3485 dummy_arg(segment.ident, guar),
3486 Trailing::No,
3487 UsePreAttrPos::No,
3488 ));
3489 }
3490
3491 if this.token != token::Comma && this.token != token::CloseParen {
3492 ty = this.unexpected_any();
3495 }
3496 }
3497 match ty {
3498 Ok(ty) => {
3499 let pat = this.mk_pat(ty.span, PatKind::Missing);
3500 (Box::new(pat), ty)
3501 }
3502 Err(err) if this.token == token::DotDotDot => return Err(err),
3504 Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
3505 Err(err) if recover_arg_parse => {
3506 err.cancel();
3508 this.restore_snapshot(parser_snapshot_before_ty);
3509 this.recover_arg_parse()?
3510 }
3511 Err(err) => return Err(err),
3512 }
3513 };
3514
3515 let span = lo.to(this.prev_token.span);
3516
3517 Ok((
3518 Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
3519 Trailing::No,
3520 UsePreAttrPos::No,
3521 ))
3522 })
3523 }
3524
3525 fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
3527 let expect_self_ident = |this: &mut Self| match this.token.ident() {
3529 Some((ident, IdentIsRaw::No)) => {
3530 this.bump();
3531 ident
3532 }
3533 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3534 };
3535 let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime());
3537 let is_isolated_self = |this: &Self, n| {
3539 this.is_keyword_ahead(n, &[kw::SelfLower])
3540 && this.look_ahead(n + 1, |t| t != &token::PathSep)
3541 };
3542 let is_isolated_pin_const_self = |this: &Self, n| {
3544 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3545 && this.is_keyword_ahead(n + 1, &[kw::Const])
3546 && is_isolated_self(this, n + 2)
3547 };
3548 let is_isolated_mut_self =
3550 |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
3551 let is_isolated_pin_mut_self = |this: &Self, n| {
3553 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3554 && is_isolated_mut_self(this, n + 1)
3555 };
3556 let parse_self_possibly_typed = |this: &mut Self, m| {
3558 let eself_ident = expect_self_ident(this);
3559 let eself_hi = this.prev_token.span;
3560 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)) {
3561 SelfKind::Explicit(this.parse_ty()?, m)
3562 } else {
3563 SelfKind::Value(m)
3564 };
3565 Ok((eself, eself_ident, eself_hi))
3566 };
3567 let expect_self_ident_not_typed =
3568 |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
3569 let eself_ident = expect_self_ident(this);
3570
3571 if this.may_recover() && this.eat_noexpect(&token::Colon) {
3573 let snap = this.create_snapshot_for_diagnostic();
3574 match this.parse_ty() {
3575 Ok(ty) => {
3576 this.dcx().emit_err(diagnostics::IncorrectTypeOnSelf {
3577 span: ty.span,
3578 move_self_modifier: diagnostics::MoveSelfModifier {
3579 removal_span: modifier_span,
3580 insertion_span: ty.span.shrink_to_lo(),
3581 modifier: modifier.to_ref_suggestion(),
3582 },
3583 });
3584 }
3585 Err(diag) => {
3586 diag.cancel();
3587 this.restore_snapshot(snap);
3588 }
3589 }
3590 }
3591 eself_ident
3592 };
3593 let recover_self_ptr = |this: &mut Self| {
3595 this.dcx().emit_err(diagnostics::SelfArgumentPointer { span: this.token.span });
3596
3597 Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
3598 };
3599
3600 let eself_lo = self.token.span;
3604 let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
3605 token::And => {
3606 let has_lifetime = is_lifetime(self, 1);
3607 let skip_lifetime_count = has_lifetime as usize;
3608 let eself = if is_isolated_self(self, skip_lifetime_count + 1) {
3609 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3612 SelfKind::Region(lifetime, Mutability::Not)
3613 } else if is_isolated_mut_self(self, skip_lifetime_count + 1) {
3614 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3617 self.bump(); SelfKind::Region(lifetime, Mutability::Mut)
3619 } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) {
3620 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3623 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3624 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Not)
3627 } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) {
3628 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3631 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3632 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Mut)
3635 } else {
3636 return Ok(None);
3638 };
3639 let hi = self.token.span;
3640 let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
3641 (eself, self_ident, hi)
3642 }
3643 token::Star if is_isolated_self(self, 1) => {
3645 self.bump();
3646 recover_self_ptr(self)?
3647 }
3648 token::Star
3650 if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
3651 {
3652 self.bump();
3653 self.bump();
3654 recover_self_ptr(self)?
3655 }
3656 token::Ident(..) if is_isolated_self(self, 0) => {
3658 parse_self_possibly_typed(self, Mutability::Not)?
3659 }
3660 token::Ident(..) if is_isolated_mut_self(self, 0) => {
3662 self.bump();
3663 parse_self_possibly_typed(self, Mutability::Mut)?
3664 }
3665 _ => return Ok(None),
3666 };
3667
3668 let eself = respan(eself_lo.to(eself_hi), eself);
3669 Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
3670 }
3671
3672 fn is_named_param(&self) -> bool {
3673 let offset = match &self.token.kind {
3674 token::OpenInvisible(origin) => match origin {
3675 InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
3676 return self.check_noexpect_past_close_delim(&token::Colon);
3677 }
3678 _ => 0,
3679 },
3680 token::And | token::AndAnd => 1,
3681 _ if self.token.is_keyword(kw::Mut) => 1,
3682 _ => 0,
3683 };
3684
3685 self.look_ahead(offset, |t| t.is_ident())
3686 && self.look_ahead(offset + 1, |t| t == &token::Colon)
3687 }
3688
3689 fn recover_self_param(&mut self) -> bool {
3690 #[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!(
3691 self.parse_outer_attributes()
3692 .and_then(|_| self.parse_self_param())
3693 .map_err(|e| e.cancel()),
3694 Ok(Some(_))
3695 )
3696 }
3697
3698 fn try_recover_const_missing_semi(
3706 &mut self,
3707 rhs: &Option<Box<Expr>>,
3708 const_span: Span,
3709 ) -> Option<Box<Expr>> {
3710 if self.token == TokenKind::Semi {
3711 return None;
3712 }
3713 let Some(rhs) = rhs else {
3714 return None;
3715 };
3716 if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
3717 return None;
3718 }
3719 if let Some((span, guar)) =
3720 self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
3721 {
3722 self.fn_body_missing_semi_guar = Some(guar);
3723 Some(self.mk_expr(span, ExprKind::Err(guar)))
3724 } else {
3725 None
3726 }
3727 }
3728}
3729
3730enum IsMacroRulesItem {
3731 Yes { has_bang: bool },
3732 No,
3733}
3734
3735#[derive(#[automatically_derived]
impl ::core::marker::Copy for FrontMatterParsingMode { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FrontMatterParsingMode {
#[inline]
fn clone(&self) -> FrontMatterParsingMode { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for FrontMatterParsingMode {
#[inline]
fn eq(&self, other: &FrontMatterParsingMode) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FrontMatterParsingMode {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
3736pub(super) enum FrontMatterParsingMode {
3737 Function,
3739 FunctionPtrType,
3742}