1use std::fmt::Write;
2use std::mem;
3
4use ast::token::IdentKind;
5use rustc_ast as ast;
6use rustc_ast::ast::*;
7use rustc_ast::token::{self, Delimiter, 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_span::edit_distance::edit_distance;
14use rustc_span::edition::Edition;
15use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
16use thin_vec::{ThinVec, thin_vec};
17use tracing::debug;
18
19use super::diagnostics::ConsumeClosingDelim;
20use super::{
21 AllowConstBlockItems, AttrWrapper, ExpTokenPair, FnContext, FnParseMode, FollowedByType,
22 ForceCollect, IsDotDotDot, Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,
23};
24use crate::diagnostics::{
25 self, MacroExpandsToAdtField, UseDoubleColonSuggestion, UseRegularStructSuggestion,
26};
27use crate::exp;
28
29impl<'a> Parser<'a> {
30 pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
32 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))?;
33 Ok(ast::Crate { attrs, items, spans, id: DUMMY_NODE_ID, is_placeholder: false })
34 }
35
36 fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
38 let safety = self.parse_safety(Case::Sensitive);
39 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mod,
token_type: crate::parser::token_type::TokenType::KwMod,
}exp!(Mod))?;
40 let ident = self.parse_ident()?;
41 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)) {
42 ModKind::Unloaded
43 } else {
44 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
45 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))?;
46 attrs.extend(inner_attrs);
47 ModKind::Loaded(items, Inline::Yes, inner_span)
48 };
49 Ok(ItemKind::Mod(safety, ident, mod_kind))
50 }
51
52 pub fn parse_mod(
57 &mut self,
58 term: ExpTokenPair,
59 ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
60 let lo = self.token.span;
61 let attrs = self.parse_inner_attributes()?;
62
63 let post_attr_lo = self.token.span;
64 let mut items: ThinVec<Box<_>> = ThinVec::new();
65
66 loop {
69 while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else {
71 break;
72 };
73 items.push(item);
74 }
75
76 if !self.eat(term) {
77 let token_str = super::token_descr(&self.token);
78 if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
79 let is_let = self.token.is_keyword(kw::Let);
80 let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
81 let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);
82
83 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected item, found {0}",
token_str))
})format!("expected item, found {token_str}");
84 let mut err = self.dcx().struct_span_err(self.token.span, msg);
85
86 let label = if is_let {
87 "`let` cannot be used for global variables"
88 } else {
89 "expected item"
90 };
91 err.span_label(self.token.span, label);
92
93 if is_let {
94 if is_let_mut {
95 err.help("consider using `static` and a `Mutex` instead of `let mut`");
96 } else if let_has_ident {
97 err.span_suggestion_short(
98 self.token.span,
99 "consider using `static` or `const` instead of `let`",
100 "static",
101 Applicability::MaybeIncorrect,
102 );
103 } else {
104 err.help("consider using `static` or `const` instead of `let`");
105 }
106 }
107 err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
108 return Err(err);
109 }
110 }
111
112 let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo());
113 let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };
114 Ok((attrs, items, mod_spans))
115 }
116}
117
118enum ReuseKind {
119 Path,
120 Impl,
121}
122
123impl<'a> Parser<'a> {
124 pub fn parse_item(
125 &mut self,
126 force_collect: ForceCollect,
127 allow_const_block_items: AllowConstBlockItems,
128 ) -> PResult<'a, Option<Box<Item>>> {
129 let fn_parse_mode =
130 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
131 self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items)
132 .map(|i| i.map(Box::new))
133 }
134
135 fn parse_item_(
136 &mut self,
137 fn_parse_mode: FnParseMode,
138 force_collect: ForceCollect,
139 const_block_items_allowed: AllowConstBlockItems,
140 ) -> PResult<'a, Option<Item>> {
141 self.recover_vcs_conflict_marker();
142 let attrs = self.parse_outer_attributes()?;
143 self.recover_vcs_conflict_marker();
144 self.parse_item_common(
145 attrs,
146 true,
147 false,
148 fn_parse_mode,
149 force_collect,
150 const_block_items_allowed,
151 )
152 }
153
154 pub(super) fn parse_item_common(
155 &mut self,
156 attrs: AttrWrapper,
157 mac_allowed: bool,
158 attrs_allowed: bool,
159 fn_parse_mode: FnParseMode,
160 force_collect: ForceCollect,
161 allow_const_block_items: AllowConstBlockItems,
162 ) -> PResult<'a, Option<Item>> {
163 if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| {
164 this.parse_item(ForceCollect::Yes, allow_const_block_items)
165 }) {
166 let mut item = item.expect("an actual item");
167 attrs.prepend_to_nt_inner(&mut item.attrs);
168 return Ok(Some(*item));
169 }
170
171 self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {
172 let lo = this.token.span;
173 let vis = this.parse_visibility(FollowedByType::No)?;
174 let mut def = this.parse_defaultness();
175 let kind = this.parse_item_kind(
176 &mut attrs,
177 mac_allowed,
178 allow_const_block_items,
179 lo,
180 &vis,
181 &mut def,
182 fn_parse_mode,
183 Case::Sensitive,
184 )?;
185 if let Some(kind) = kind {
186 this.error_on_unconsumed_default(def, &kind);
187 let span = lo.to(this.prev_token.span);
188 let id = DUMMY_NODE_ID;
189 let item = Item { attrs, id, kind, vis, span, tokens: None };
190 return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
191 }
192
193 if !#[allow(non_exhaustive_omitted_patterns)] match vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(vis.kind, VisibilityKind::Inherited) {
195 let vis_str = pprust::vis_to_string(&vis).trim_end().to_string();
196 let mut err = this.dcx().create_err(diagnostics::VisibilityNotFollowedByItem {
197 span: vis.span,
198 vis: vis_str,
199 });
200 if let Some((ident, _)) = this.token.ident()
201 && !ident.is_used_keyword()
202 && let Some((similar_kw, is_incorrect_case)) = ident
203 .name
204 .find_similar(&rustc_span::symbol::used_keywords(|| ident.span.edition()))
205 {
206 err.subdiagnostic(diagnostics::MisspelledKw {
207 similar_kw: similar_kw.to_string(),
208 span: ident.span,
209 is_incorrect_case,
210 });
211 }
212 err.emit();
213 }
214
215 if let Defaultness::Default(span) = def {
216 this.dcx().emit_err(diagnostics::DefaultNotFollowedByItem { span });
217 } else if let Defaultness::Final(span) = def {
218 this.dcx().emit_err(diagnostics::FinalNotFollowedByItem { span });
219 }
220
221 if !attrs_allowed {
222 this.recover_attrs_no_item(&attrs)?;
223 }
224 Ok((None, Trailing::No, UsePreAttrPos::No))
225 })
226 }
227
228 fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
230 match def {
231 Defaultness::Default(span) => {
232 self.dcx().emit_err(diagnostics::InappropriateDefault {
233 span,
234 article: kind.article(),
235 descr: kind.descr(),
236 });
237 }
238 Defaultness::Final(span) => {
239 self.dcx().emit_err(diagnostics::InappropriateFinal {
240 span,
241 article: kind.article(),
242 descr: kind.descr(),
243 });
244 }
245 Defaultness::Implicit => (),
246 }
247 }
248
249 fn parse_item_kind(
251 &mut self,
252 attrs: &mut AttrVec,
253 macros_allowed: bool,
254 allow_const_block_items: AllowConstBlockItems,
255 lo: Span,
256 vis: &Visibility,
257 def: &mut Defaultness,
258 fn_parse_mode: FnParseMode,
259 case: Case,
260 ) -> PResult<'a, Option<ItemKind>> {
261 let check_pub = def == &Defaultness::Implicit;
262 let mut def_ = || mem::replace(def, Defaultness::Implicit);
263
264 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) {
265 self.parse_use_item()?
266 } else if self.check_fn_front_matter(check_pub, case) {
267 let defaultness = def_();
269 if let Defaultness::Default(span) = defaultness {
270 self.psess.gated_spans.gate(sym::min_specialization, span);
274 self.psess.gated_spans.ungate_last(sym::specialization, span);
275 }
276 let (ident, sig, generics, contract, body) =
277 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
278 ItemKind::Fn(Box::new(Fn {
279 defaultness,
280 ident,
281 sig,
282 generics,
283 contract,
284 body,
285 define_opaque: None,
286 eii_impl: None,
287 }))
288 } 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) {
289 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) {
290 self.parse_item_extern_crate()?
292 } else {
293 self.parse_item_foreign_mod(attrs, Safety::Default)?
295 }
296 } else if self.is_unsafe_foreign_mod() {
297 let safety = self.parse_safety(Case::Sensitive);
299 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern))?;
300 self.parse_item_foreign_mod(attrs, safety)?
301 } else if let Some(safety) = self.parse_global_static_front_matter(case) {
302 let mutability = self.parse_mutability();
304 self.parse_static_item(safety, mutability)?
305 } 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() {
306 self.parse_item_trait(attrs, lo)?
308 } else if self.check_impl_frontmatter(0) {
309 self.parse_item_impl(attrs, def_(), false)?
311 } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
312 allow_const_block_items
313 && self.check_inline_const(0)
314 {
315 if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
317 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/2311729bc1fb3f2e001e5c52c45eac94019a4fd5/compiler/rustc_parse/src/parser/item.rs:317",
"rustc_parse::parser::item", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/2311729bc1fb3f2e001e5c52c45eac94019a4fd5/compiler/rustc_parse/src/parser/item.rs"),
::tracing_core::__macro_support::Option::Some(317u32),
::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);
318 };
319 ItemKind::ConstBlock(self.parse_const_block_item()?)
320 } else if let Const::Yes(const_span) = self.parse_constness(case) {
321 self.recover_const_mut(const_span);
323 self.recover_missing_kw_before_item()?;
324 let (ident, generics, ty, body) = self.parse_const_item(const_span)?;
325 ItemKind::Const(Box::new(ConstItem {
326 defaultness: def_(),
327 ident,
328 generics,
329 ty,
330 body,
331 define_opaque: None,
332 }))
333 } else if let Some(kind) = self.is_reuse_item() {
334 self.parse_item_delegation(attrs, def_(), kind)?
335 } 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)
336 || 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])
337 {
338 self.parse_item_mod(attrs)?
340 } 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) {
341 self.parse_type_alias(def_())?
343 } 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) {
344 self.parse_item_enum()?
346 } 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) {
347 self.parse_item_struct()?
349 } else if self.is_kw_followed_by_ident(kw::Union) {
350 self.bump(); self.parse_item_union()?
353 } else if self.is_builtin() {
354 return self.parse_item_builtin();
356 } 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) {
357 self.parse_item_decl_macro(lo)?
359 } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
360 self.parse_item_macro_rules(vis, has_bang)?
362 } else if self.isnt_macro_invocation()
363 && (self.token.is_ident_named(sym::import)
364 || self.token.is_ident_named(sym::using)
365 || self.token.is_ident_named(sym::include)
366 || self.token.is_ident_named(sym::require))
367 {
368 return self.recover_import_as_use();
369 } else if self.isnt_macro_invocation() && vis.kind.is_pub() {
370 self.recover_missing_kw_before_item()?;
371 return Ok(None);
372 } else if self.isnt_macro_invocation() && case == Case::Sensitive {
373 _ = def_;
374
375 return self.parse_item_kind(
377 attrs,
378 macros_allowed,
379 allow_const_block_items,
380 lo,
381 vis,
382 def,
383 fn_parse_mode,
384 Case::Insensitive,
385 );
386 } else if macros_allowed && self.check_path() {
387 let is_field_in_trait = fn_parse_mode.context == FnContext::Trait
390 && self.token.is_path_start()
391 && self.look_ahead(1, |t| t.kind == token::Colon);
392 if is_field_in_trait {
393 return self.recover_field_in_trait();
394 }
395 if self.isnt_macro_invocation() {
396 self.recover_missing_kw_before_item()?;
397 }
398 ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
400 } else {
401 return Ok(None);
402 };
403 Ok(Some(info))
404 }
405
406 fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
407 let span = self.token.span;
408 let token_name = super::token_descr(&self.token);
409 let snapshot = self.create_snapshot_for_diagnostic();
410 self.bump();
411 match self.parse_use_item() {
412 Ok(u) => {
413 self.dcx().emit_err(diagnostics::RecoverImportAsUse { span, token_name });
414 Ok(Some(u))
415 }
416 Err(e) => {
417 e.cancel();
418 self.restore_snapshot(snapshot);
419 Ok(None)
420 }
421 }
422 }
423
424 fn recover_field_in_trait(&mut self) -> PResult<'a, Option<ItemKind>> {
425 let ident_span = self.token.span;
426 let ident_str = pprust::token_to_string(&self.token).into_owned();
427 let is_self = self.token.is_keyword(kw::SelfLower);
428
429 self.bump(); self.bump(); let ty_str = match self.parse_ty() {
433 Ok(ty) => pprust::ty_to_string(&ty),
434 Err(e) => {
435 e.cancel();
436 String::from("Type")
437 }
438 };
439 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
441 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi));
442
443 let span = ident_span.to(self.prev_token.span);
444 let sugg = if is_self {
445 diagnostics::FieldNotAllowedInTraitSugg::SelfReceiver { ty: ty_str }
446 } else {
447 diagnostics::FieldNotAllowedInTraitSugg::Method { ident: ident_str, ty: ty_str }
448 };
449 let err = self.dcx().create_err(diagnostics::FieldNotAllowedInTrait { span, sugg });
450 Err(err)
451 }
452
453 fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
454 let use_token_span = self.prev_token.span;
455 let tree = self.parse_use_tree(use_token_span, None)?;
456 if let Err(mut e) = self.expect_semi() {
457 match tree.kind {
458 UseTreeKind::Glob(_) => {
459 e.note("the wildcard token must be last on the path");
460 }
461 UseTreeKind::Nested { .. } => {
462 e.note("glob-like brace syntax must be last on the path");
463 }
464 _ => (),
465 }
466 return Err(e);
467 }
468 Ok(ItemKind::Use(tree))
469 }
470
471 pub(super) fn is_path_start_item(&mut self) -> bool {
473 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{..}) }
479
480 fn is_reuse_item(&mut self) -> Option<ReuseKind> {
481 if !self.token.is_keyword(kw::Reuse) {
482 return None;
483 }
484
485 if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
487 Some(ReuseKind::Path)
488 } else if self.check_impl_frontmatter(1) {
489 Some(ReuseKind::Impl)
490 } else {
491 None
492 }
493 }
494
495 fn isnt_macro_invocation(&mut self) -> bool {
497 self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
498 }
499
500 fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
503 let is_pub = self.prev_token.is_keyword(kw::Pub);
504 let is_const = self.prev_token.is_keyword(kw::Const);
505 let ident_span = self.token.span;
506 let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };
507 let insert_span = ident_span.shrink_to_lo();
508
509 let ident = if self.token.is_ident()
510 && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
511 && self.look_ahead(1, |t| {
512 #[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)
513 }) {
514 self.parse_ident_common(true).unwrap()
515 } else {
516 return Ok(());
517 };
518
519 let mut found_generics = false;
520 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Lt,
token_type: crate::parser::token_type::TokenType::Lt,
}exp!(Lt)) {
521 found_generics = true;
522 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Gt,
token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)]);
523 self.bump(); }
525
526 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)) {
527 if self.look_ahead(1, |t| *t == token::CloseBrace) {
529 Some(diagnostics::MissingKeywordForItemDefinition::EnumOrStruct { span })
531 } else if self.look_ahead(2, |t| *t == token::Colon)
532 || self.look_ahead(3, |t| *t == token::Colon)
533 {
534 Some(diagnostics::MissingKeywordForItemDefinition::Struct {
536 span,
537 insert_span,
538 ident,
539 })
540 } else {
541 Some(diagnostics::MissingKeywordForItemDefinition::Enum {
542 span,
543 insert_span,
544 ident,
545 })
546 }
547 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
548 self.bump(); let is_method = self.recover_self_param();
551
552 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);
553
554 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)) {
555 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)]);
556 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);
558 if is_method {
559 diagnostics::MissingKeywordForItemDefinition::Method {
560 span,
561 insert_span,
562 ident,
563 }
564 } else {
565 diagnostics::MissingKeywordForItemDefinition::Function {
566 span,
567 insert_span,
568 ident,
569 }
570 }
571 } 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)) {
572 diagnostics::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
573 } else {
574 diagnostics::MissingKeywordForItemDefinition::Ambiguous {
575 span,
576 subdiag: if found_generics {
577 None
578 } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
579 Some(diagnostics::AmbiguousMissingKwForItemSub::SuggestMacro {
580 span: ident_span,
581 snippet,
582 })
583 } else {
584 Some(diagnostics::AmbiguousMissingKwForItemSub::HelpMacro)
585 },
586 }
587 };
588 Some(err)
589 } else if found_generics {
590 Some(diagnostics::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
591 } else {
592 None
593 };
594
595 if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
596 }
597
598 fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
599 Ok(None)
601 }
602
603 fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
605 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() {
608 Ok(args) => {
610 self.eat_semi_for_macro_if_needed(&args, Some(&path));
611 self.complain_if_pub_macro(vis, false);
612 Ok(MacCall { path, args })
613 }
614
615 Err(mut err) => {
616 if self.token.is_ident()
618 && let [segment] = path.segments.as_slice()
619 && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
620 {
621 err.span_suggestion_verbose(
622 path.span,
623 "perhaps you meant to define a macro",
624 "macro_rules",
625 Applicability::MachineApplicable,
626 );
627 }
628 Err(err)
629 }
630 }
631 }
632
633 fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
635 let ([start @ end] | [start, .., end]) = attrs else {
636 return Ok(());
637 };
638 let msg = if end.is_doc_comment() {
639 "expected item after doc comment"
640 } else {
641 "expected item after attributes"
642 };
643 let mut err = self.dcx().struct_span_err(end.span, msg);
644 if end.is_doc_comment() {
645 err.span_label(end.span, "this doc comment doesn't document anything");
646 } else {
647 err.span_label(end.span, "expected an item after this");
648 if self.token == TokenKind::Semi {
649 err.span_suggestion_verbose(
650 self.token.span,
651 "remove the semicolon after the attribute",
652 "",
653 Applicability::MaybeIncorrect,
654 );
655 }
656 }
657 if let [.., penultimate, _] = attrs {
658 err.span_label(start.span.to(penultimate.span), "other attributes here");
659 }
660 Err(err)
661 }
662
663 fn is_async_fn(&self) -> bool {
664 self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
665 }
666
667 fn parse_polarity(&mut self) -> ast::ImplPolarity {
668 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()) {
670 self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
671 self.bump(); ast::ImplPolarity::Negative(self.prev_token.span)
673 } else {
674 ast::ImplPolarity::Positive
675 }
676 }
677
678 fn parse_item_impl(
693 &mut self,
694 attrs: &mut AttrVec,
695 defaultness: Defaultness,
696 is_reuse: bool,
697 ) -> PResult<'a, ItemKind> {
698 let constness = self.parse_constness(Case::Sensitive);
699 let safety = self.parse_safety(Case::Sensitive);
700 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
701 let mut generics_snapshot = None;
702 let mut generics = if self.choose_generics_over_qpath(0) {
704 self.parse_generics()?
705 } else {
706 if self.look_ahead(0, |t| t == &token::Lt)
709 && self.look_ahead(1, |t| t.is_ident())
710 && self.look_ahead(2, |t| t == &token::Lt)
711 {
712 generics_snapshot = Some(self.create_snapshot_for_diagnostic());
713 }
714
715 let mut generics = Generics::default();
716 generics.span = self.prev_token.span.shrink_to_hi();
719 generics
720 };
721
722 if let Const::Yes(span) = constness {
723 self.psess.gated_spans.gate(sym::const_trait_impl, span);
724 }
725
726 if (self.token_uninterpolated_span().at_least_rust_2018()
728 && self.token.is_keyword(kw::Async))
729 || self.is_kw_followed_by_ident(kw::Async)
730 {
731 self.bump();
732 self.dcx().emit_err(diagnostics::AsyncImpl { span: self.prev_token.span });
733 }
734
735 let polarity = self.parse_polarity();
736
737 let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
739 {
740 let span = self.prev_token.span.between(self.token.span);
741 return Err(self.dcx().create_err(diagnostics::MissingTraitInTraitImpl {
742 span,
743 for_span: span.to(self.token.span),
744 }));
745 } else {
746 self.parse_ty_with_generics_recovery(&generics).map_err(|e| {
747 let Some(mut snapshot) = generics_snapshot else {
748 return e;
749 };
750 snapshot.maybe_type_in_generic_parameter(e)
751 })?
752 };
753 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));
755 let missing_for_span = self.prev_token.span.between(self.token.span);
756
757 let ty_second = if self.token == token::DotDot {
758 self.bump(); Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
765 } else if has_for || self.token.can_begin_type() {
766 Some(self.parse_ty()?)
767 } else {
768 None
769 };
770
771 generics.where_clause = self.parse_where_clause()?;
772
773 let impl_items = if is_reuse {
774 Default::default()
775 } else {
776 self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
777 };
778
779 let (of_trait, self_ty) = match ty_second {
780 Some(ty_second) => {
781 if !has_for {
783 self.dcx()
784 .emit_err(diagnostics::MissingForInTraitImpl { span: missing_for_span });
785 }
786
787 let ty_first = *ty_first;
788 let path = match ty_first.kind {
789 TyKind::Path(None, path) => path,
791 other => {
792 if let TyKind::ImplTrait(_, bounds) = other
793 && let [bound] = bounds.as_slice()
794 && let GenericBound::Trait(poly_trait_ref) = bound
795 {
796 let extra_impl_kw = ty_first.span.until(bound.span());
800 self.dcx().emit_err(diagnostics::ExtraImplKeywordInTraitImpl {
801 extra_impl_kw,
802 impl_trait_span: ty_first.span,
803 });
804 poly_trait_ref.trait_ref.path.clone()
805 } else {
806 return Err(self.dcx().create_err(
807 diagnostics::ExpectedTraitInTraitImplFoundType {
808 span: ty_first.span,
809 },
810 ));
811 }
812 }
813 };
814 let trait_ref = TraitRef { path, ref_id: ty_first.id };
815
816 let of_trait =
817 Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
818 (of_trait, ty_second)
819 }
820 None => {
821 let self_ty = ty_first;
822 let error = |modifier, modifier_name, modifier_span| {
823 self.dcx().create_err(diagnostics::TraitImplModifierInInherentImpl {
824 span: self_ty.span,
825 modifier,
826 modifier_name,
827 modifier_span,
828 self_ty: self_ty.span,
829 })
830 };
831
832 if let Safety::Unsafe(span) = safety {
833 error("unsafe", "unsafe", span).with_code(E0197).emit();
834 }
835 if let ImplPolarity::Negative(span) = polarity {
836 error("!", "negative", span).emit();
837 }
838 if let Defaultness::Default(def_span) = defaultness {
839 error("default", "default", def_span).emit();
840 }
841 if let Const::Yes(span) = constness {
842 self.psess.gated_spans.gate(sym::const_trait_impl, span);
843 }
844 (None, self_ty)
845 }
846 };
847
848 Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
849 }
850
851 fn parse_item_delegation(
852 &mut self,
853 attrs: &mut AttrVec,
854 defaultness: Defaultness,
855 kind: ReuseKind,
856 ) -> PResult<'a, ItemKind> {
857 let span = self.token.span;
858 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Reuse,
token_type: crate::parser::token_type::TokenType::KwReuse,
}exp!(Reuse))?;
859
860 let item_kind = match kind {
861 ReuseKind::Path => self.parse_path_like_delegation(),
862 ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
863 }?;
864
865 self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
866
867 Ok(item_kind)
868 }
869
870 fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
871 Ok(if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
872 Some(self.parse_block()?)
873 } else {
874 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))?;
875 None
876 })
877 }
878
879 fn parse_impl_delegation(
880 &mut self,
881 span: Span,
882 attrs: &mut AttrVec,
883 defaultness: Defaultness,
884 ) -> PResult<'a, ItemKind> {
885 let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
886 let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
887
888 let until_expr_span = span.to(self.prev_token.span);
889
890 let Some(of_trait) = of_trait else {
891 return Err(self
892 .dcx()
893 .create_err(diagnostics::ImplReuseInherentImpl { span: until_expr_span }));
894 };
895
896 let body = self.parse_delegation_body()?;
897 let whole_reuse_span = span.to(self.prev_token.span);
898
899 items.push(Box::new(AssocItem {
900 id: DUMMY_NODE_ID,
901 attrs: Default::default(),
902 span: whole_reuse_span,
903 tokens: None,
904 vis: Visibility { kind: VisibilityKind::Inherited, span: whole_reuse_span },
905 kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
906 qself: None,
907 prefix: of_trait.trait_ref.path.clone(),
908 suffixes: DelegationSuffixes::Glob(whole_reuse_span),
909 body,
910 })),
911 }));
912
913 Ok(impl_item)
914 }
915
916 fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
917 let (qself, path) = if self.eat_lt() {
918 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
919 (Some(qself), path)
920 } else {
921 (None, self.parse_path(PathStyle::Expr)?)
922 };
923
924 let rename = |this: &mut Self| {
925 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 })
926 };
927
928 Ok(if self.eat_path_sep() {
929 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)) {
930 DelegationSuffixes::Glob(self.prev_token.span)
931 } else {
932 let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
933 DelegationSuffixes::List(
934 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,
935 )
936 };
937
938 ItemKind::DelegationMac(Box::new(DelegationMac {
939 qself,
940 prefix: path,
941 suffixes,
942 body: self.parse_delegation_body()?,
943 }))
944 } else {
945 let rename = rename(self)?;
946 let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
947
948 ItemKind::Delegation(Box::new(Delegation {
949 id: DUMMY_NODE_ID,
950 qself,
951 path,
952 ident,
953 rename,
954 body: self.parse_delegation_body()?,
955 source: DelegationSource::Single,
956 }))
957 })
958 }
959
960 fn parse_item_list<T>(
961 &mut self,
962 attrs: &mut AttrVec,
963 mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
964 ) -> PResult<'a, ThinVec<T>> {
965 let open_brace_span = self.token.span;
966
967 if self.token == TokenKind::Semi {
969 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
970 self.bump();
971 return Ok(ThinVec::new());
972 }
973
974 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
975 attrs.extend(self.parse_inner_attributes()?);
976
977 let mut items = ThinVec::new();
978 while !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)) {
979 if self.recover_doc_comment_before_brace() {
980 continue;
981 }
982 self.recover_vcs_conflict_marker();
983 match parse_item(self) {
984 Ok(None) => {
985 let mut is_unnecessary_semicolon = (self.token == token::Semi
986 && self.prev_token == token::Semi)
987 || !items.is_empty()
988 && self
1006 .span_to_snippet(self.prev_token.span)
1007 .is_ok_and(|snippet| snippet == "}")
1008 && self.token == token::Semi;
1009 let mut semicolon_span = self.token.span;
1010 if !is_unnecessary_semicolon {
1011 is_unnecessary_semicolon =
1013 self.token == token::OpenBrace && self.prev_token == token::Semi;
1014 semicolon_span = self.prev_token.span;
1015 }
1016 let non_item_span = self.token.span;
1018 let is_let = self.token.is_keyword(kw::Let);
1019
1020 let mut err =
1021 self.dcx().struct_span_err(non_item_span, "non-item in item list");
1022 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);
1023 if is_let {
1024 err.span_suggestion_verbose(
1025 non_item_span,
1026 "consider using `const` instead of `let` for associated const",
1027 "const",
1028 Applicability::MachineApplicable,
1029 );
1030 } else {
1031 err.span_label(open_brace_span, "item list starts here")
1032 .span_label(non_item_span, "non-item starts here")
1033 .span_label(self.prev_token.span, "item list ends here");
1034 }
1035 if is_unnecessary_semicolon {
1036 err.span_suggestion_verbose(
1037 semicolon_span,
1038 "consider removing this semicolon",
1039 "",
1040 Applicability::MaybeIncorrect,
1041 );
1042 }
1043 err.emit();
1044 break;
1045 }
1046 Ok(Some(item)) => items.extend(item),
1047 Err(err) => {
1048 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);
1049 err.with_span_label(
1050 open_brace_span,
1051 "while parsing this item list starting here",
1052 )
1053 .with_span_label(self.prev_token.span, "the item list ends here")
1054 .emit();
1055 break;
1056 }
1057 }
1058 }
1059 Ok(items)
1060 }
1061
1062 fn recover_doc_comment_before_brace(&mut self) -> bool {
1064 if let token::DocComment(..) = self.token.kind {
1065 if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
1066 {
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!(
1068 self.dcx(),
1069 self.token.span,
1070 E0584,
1071 "found a documentation comment that doesn't document anything",
1072 )
1073 .with_span_label(self.token.span, "this doc comment doesn't document anything")
1074 .with_help(
1075 "doc comments must come before what they document, if a comment was \
1076 intended use `//`",
1077 )
1078 .emit();
1079 self.bump();
1080 return true;
1081 }
1082 }
1083 false
1084 }
1085
1086 fn parse_defaultness(&mut self) -> Defaultness {
1088 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))
1092 && self.look_ahead(1, |t| t.non_raw_ident().is_some_and(|i| i.name != kw::As))
1093 {
1094 self.psess.gated_spans.gate(sym::specialization, self.token.span);
1095 self.bump(); Defaultness::Default(self.prev_token_uninterpolated_span())
1097 } 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)) {
1098 self.psess.gated_spans.gate(sym::final_associated_functions, self.prev_token.span);
1099 Defaultness::Final(self.prev_token_uninterpolated_span())
1100 } else {
1101 Defaultness::Implicit
1102 }
1103 }
1104
1105 fn check_trait_front_matter(&mut self) -> bool {
1107 const SUFFIXES: &[&[Symbol]] = &[
1108 &[kw::Trait],
1109 &[kw::Auto, kw::Trait],
1110 &[kw::Unsafe, kw::Trait],
1111 &[kw::Unsafe, kw::Auto, kw::Trait],
1112 &[kw::Const, kw::Trait],
1113 &[kw::Const, kw::Auto, kw::Trait],
1114 &[kw::Const, kw::Unsafe, kw::Trait],
1115 &[kw::Const, kw::Unsafe, kw::Auto, kw::Trait],
1116 ];
1117 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) {
1119 if self.is_keyword_ahead(2, &[kw::In]) {
1121 return true;
1122 }
1123 if self.is_keyword_ahead(2, &[kw::Crate, kw::SelfLower, kw::Super])
1125 && self.look_ahead(3, |t| t == &token::CloseParen)
1126 && SUFFIXES.iter().any(|suffix| {
1127 suffix.iter().enumerate().all(|(i, kw)| self.is_keyword_ahead(i + 4, &[*kw]))
1128 })
1129 {
1130 return true;
1131 }
1132 SUFFIXES.iter().any(|suffix| {
1134 suffix.iter().enumerate().all(|(i, kw)| {
1135 self.tree_look_ahead(i + 2, |t| {
1136 if let TokenTree::Token(token, _) = t {
1137 token.is_keyword(*kw)
1138 } else {
1139 false
1140 }
1141 })
1142 .unwrap_or(false)
1143 })
1144 })
1145 } else {
1146 SUFFIXES.iter().any(|suffix| {
1147 suffix.iter().enumerate().all(|(i, kw)| {
1148 if i == 0 {
1150 match *kw {
1151 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)),
1152 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)),
1153 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)),
1154 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)),
1155 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1156 }
1157 } else {
1158 self.is_keyword_ahead(i, &[*kw])
1159 }
1160 })
1161 })
1162 }
1163 }
1164
1165 fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
1167 let impl_restriction = self.parse_impl_restriction()?;
1168 let constness = self.parse_constness(Case::Sensitive);
1169 if let Const::Yes(span) = constness {
1170 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1171 }
1172 let safety = self.parse_safety(Case::Sensitive);
1173 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)) {
1175 self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
1176 IsAuto::Yes
1177 } else {
1178 IsAuto::No
1179 };
1180
1181 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait))?;
1182 let ident = self.parse_ident()?;
1183 let mut generics = self.parse_generics()?;
1184
1185 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));
1187 let span_at_colon = self.prev_token.span;
1188 let bounds = if had_colon { self.parse_generic_bounds()? } else { ThinVec::new() };
1189
1190 let span_before_eq = self.prev_token.span;
1191 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1192 if had_colon {
1194 let span = span_at_colon.to(span_before_eq);
1195 self.dcx().emit_err(diagnostics::BoundsNotAllowedOnTraitAliases { span });
1196 }
1197
1198 let bounds = self.parse_generic_bounds()?;
1199 generics.where_clause = self.parse_where_clause()?;
1200 self.expect_semi()?;
1201
1202 let whole_span = lo.to(self.prev_token.span);
1203 if is_auto == IsAuto::Yes {
1204 self.dcx().emit_err(diagnostics::TraitAliasCannotBeAuto { span: whole_span });
1205 }
1206 if let Safety::Unsafe(_) = safety {
1207 self.dcx().emit_err(diagnostics::TraitAliasCannotBeUnsafe { span: whole_span });
1208 }
1209 if let RestrictionKind::Restricted { .. } = impl_restriction.kind {
1210 self.dcx()
1211 .emit_err(diagnostics::TraitAliasCannotBeImplRestricted { span: whole_span });
1212 }
1213
1214 self.psess.gated_spans.gate(sym::trait_alias, whole_span);
1215
1216 Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
1217 } else {
1218 generics.where_clause = self.parse_where_clause()?;
1220 let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
1221 Ok(ItemKind::Trait(Box::new(Trait {
1222 impl_restriction,
1223 constness,
1224 is_auto,
1225 safety,
1226 ident,
1227 generics,
1228 bounds,
1229 items,
1230 })))
1231 }
1232 }
1233
1234 pub fn parse_impl_item(
1235 &mut self,
1236 force_collect: ForceCollect,
1237 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1238 let fn_parse_mode =
1239 FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
1240 self.parse_assoc_item(fn_parse_mode, force_collect)
1241 }
1242
1243 pub fn parse_trait_item(
1244 &mut self,
1245 force_collect: ForceCollect,
1246 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1247 let fn_parse_mode = FnParseMode {
1248 req_name: |edition, _| edition >= Edition::Edition2018,
1249 context: FnContext::Trait,
1250 req_body: false,
1251 };
1252 self.parse_assoc_item(fn_parse_mode, force_collect)
1253 }
1254
1255 fn parse_assoc_item(
1257 &mut self,
1258 fn_parse_mode: FnParseMode,
1259 force_collect: ForceCollect,
1260 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1261 Ok(self
1262 .parse_item_(
1263 fn_parse_mode,
1264 force_collect,
1265 AllowConstBlockItems::DoesNotMatter, )?
1267 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1268 let kind = match AssocItemKind::try_from(kind) {
1269 Ok(kind) => kind,
1270 Err(kind) => match kind {
1271 ItemKind::Static(StaticItem {
1272 ident,
1273 ty,
1274 safety: _,
1275 mutability: _,
1276 expr,
1277 define_opaque,
1278 eii_impl: _,
1279 }) => {
1280 self.dcx()
1281 .emit_err(diagnostics::AssociatedStaticItemNotAllowed { span });
1282 AssocItemKind::Const(Box::new(ConstItem {
1283 defaultness: Defaultness::Implicit,
1284 ident,
1285 generics: Generics::default(),
1286 ty,
1287 body: expr,
1288 define_opaque,
1289 }))
1290 }
1291 _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
1292 },
1293 };
1294 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1295 }))
1296 }
1297
1298 fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
1304 let ident = self.parse_ident()?;
1305 let mut generics = self.parse_generics()?;
1306
1307 let bounds =
1309 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() };
1310 generics.where_clause = self.parse_where_clause()?;
1311
1312 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 };
1313
1314 let after_where_clause = self.parse_where_clause()?;
1315
1316 self.expect_semi()?;
1317
1318 Ok(ItemKind::TyAlias(Box::new(TyAlias {
1319 defaultness,
1320 ident,
1321 generics,
1322 after_where_clause,
1323 bounds,
1324 ty,
1325 })))
1326 }
1327
1328 fn parse_use_tree<'b>(
1338 &mut self,
1339 use_token_span: Span,
1340 use_path: Option<&'b UsePathList<'b>>,
1341 ) -> PResult<'a, UseTree> {
1342 let lo = self.token.span;
1343
1344 let mut prefix = ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo() };
1345 let kind =
1346 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() {
1347 let mod_sep_ctxt = self.token.span.ctxt();
1349 if self.eat_path_sep() {
1350 prefix
1351 .segments
1352 .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
1353 }
1354
1355 self.parse_use_tree_glob_or_nested(use_token_span, use_path)?
1356 } else {
1357 prefix = self.parse_path(PathStyle::Mod)?;
1359
1360 if self.eat_path_sep() {
1361 let use_path = UsePathList { elements: &prefix.segments, prev: use_path };
1362 self.parse_use_tree_glob_or_nested(use_token_span, Some(&use_path))?
1363 } else {
1364 while self.eat_noexpect(&token::Colon) {
1366 self.dcx().emit_err(diagnostics::SingleColonImportPath {
1367 span: self.prev_token.span,
1368 });
1369
1370 self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
1372 prefix.span = lo.to(self.prev_token.span);
1373 }
1374
1375 UseTreeKind::Simple(self.parse_rename()?)
1376 }
1377 };
1378
1379 Ok(UseTree { prefix, kind })
1380 }
1381
1382 fn parse_use_tree_glob_or_nested<'b>(
1384 &mut self,
1385 use_token_span: Span,
1386 use_path: Option<&'b UsePathList<'b>>,
1387 ) -> PResult<'a, UseTreeKind> {
1388 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
1389 UseTreeKind::Glob(self.prev_token.span)
1390 } else {
1391 let lo = self.token.span;
1392 UseTreeKind::Nested {
1393 items: self.parse_use_tree_list(use_token_span, use_path)?,
1394 span: lo.to(self.prev_token.span),
1395 }
1396 })
1397 }
1398
1399 fn parse_use_tree_list<'b>(
1405 &mut self,
1406 use_token_span: Span,
1407 prefix: Option<&'b UsePathList<'b>>,
1408 ) -> PResult<'a, ThinVec<UseTreeAndId>> {
1409 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| {
1410 p.recover_vcs_conflict_marker();
1411
1412 let mut attr_span = None;
1413 let attrs = p.parse_outer_attributes()?;
1414 if !attrs.is_empty() {
1415 let raw_attrs = attrs.take_for_recovery(&p.psess);
1416 attr_span =
1417 Some(raw_attrs.first().unwrap().span.to(raw_attrs.last().unwrap().span));
1418 }
1419
1420 let use_tree = p.parse_use_tree(use_token_span, prefix)?;
1421
1422 if let Some(attr_span) = attr_span {
1423 p.emit_error_attr_in_use_tree(use_token_span, prefix, use_tree.span(), attr_span);
1424 }
1425
1426 Ok(UseTreeAndId { inner: use_tree, id: DUMMY_NODE_ID })
1427 })
1428 .map(|(r, _)| r)
1429 }
1430
1431 fn emit_error_attr_in_use_tree(
1432 &self,
1433 use_token_span: Span,
1434 mut prefix: Option<&UsePathList<'_>>,
1435 use_tree_span: Span,
1436 attr_span: Span,
1437 ) {
1438 let Ok(attr) = self.psess.source_map().span_to_snippet(attr_span) else { return };
1439
1440 let prefix: Vec<_> = {
1441 let mut tmp = Vec::new();
1442 while let Some(prefix_) = prefix {
1443 tmp.push(prefix_.elements);
1444 prefix = prefix_.prev;
1445 }
1446 tmp.reverse();
1447 tmp.into_iter().flatten().collect()
1448 };
1449
1450 let prefix: String = prefix
1451 .iter()
1452 .map(|seg| if seg.ident.name == kw::PathRoot { "" } else { seg.ident.as_str() })
1453 .intersperse("::")
1454 .collect();
1455
1456 let mut comma_reached = false;
1457 let Ok(tree_span) = self.psess.source_map().span_extend_while(use_tree_span, |c| {
1458 if comma_reached {
1459 return false;
1460 }
1461 comma_reached = c == ',';
1462 c.is_whitespace() || comma_reached
1463 }) else {
1464 return;
1465 };
1466
1467 let Ok(use_tree) = self.psess.source_map().span_to_snippet(use_tree_span) else { return };
1468
1469 let code = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}\nuse {1}::{2};\n", attr,
prefix, use_tree))
})format!("{attr}\nuse {prefix}::{use_tree};\n");
1471
1472 self.dcx().emit_err(crate::diagnostics::AttrInUseTree {
1473 attr_span,
1474 sub: Some(crate::diagnostics::AttrInUseTreeSugg {
1475 use_lo: use_token_span.shrink_to_lo(),
1476 attr_span,
1477 tree_span,
1478 code,
1479 }),
1480 });
1481 }
1482
1483 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1484 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)) {
1485 self.parse_ident_or_underscore().map(Some)
1486 } else {
1487 Ok(None)
1488 }
1489 }
1490
1491 fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
1492 if let Some(ident @ Ident { name: kw::Underscore, .. }) = self.token.non_raw_ident() {
1493 self.bump();
1494 Ok(ident)
1495 } else {
1496 self.parse_ident()
1497 }
1498 }
1499
1500 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1509 let orig_ident = self.parse_crate_name_with_dashes()?;
1511 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1512 (Some(orig_ident.name), rename)
1513 } else {
1514 (None, orig_ident)
1515 };
1516 self.expect_semi()?;
1517 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1518 }
1519
1520 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1521 let ident = if self.token.is_keyword(kw::SelfLower) {
1522 self.parse_path_segment_ident()
1523 } else {
1524 self.parse_ident()
1525 }?;
1526
1527 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1528 if self.token != dash.tok {
1529 return Ok(ident);
1530 }
1531
1532 let mut dashes = ::alloc::vec::Vec::new()vec![];
1534 let mut idents = ::alloc::vec::Vec::new()vec![];
1535 while self.eat(dash) {
1536 dashes.push(self.prev_token.span);
1537 idents.push(self.parse_ident()?);
1538 }
1539
1540 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1541 let mut fixed_name = ident.name.to_string();
1542 for part in idents {
1543 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1544 }
1545
1546 self.dcx().emit_err(diagnostics::ExternCrateNameWithDashes {
1547 span: fixed_name_sp,
1548 sugg: diagnostics::ExternCrateNameWithDashesSugg { dashes },
1549 });
1550
1551 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1552 }
1553
1554 fn parse_item_foreign_mod(
1565 &mut self,
1566 attrs: &mut AttrVec,
1567 mut safety: Safety,
1568 ) -> PResult<'a, ItemKind> {
1569 let extern_span = self.prev_token_uninterpolated_span();
1570 let abi = self.parse_abi(); if safety == Safety::Default
1573 && self.token.is_keyword(kw::Unsafe)
1574 && self.look_ahead(1, |t| *t == token::OpenBrace)
1575 {
1576 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();
1577 safety = Safety::Unsafe(self.token.span);
1578 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));
1579 }
1580 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1581 extern_span,
1582 safety,
1583 abi,
1584 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1585 }))
1586 }
1587
1588 pub fn parse_foreign_item(
1590 &mut self,
1591 force_collect: ForceCollect,
1592 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1593 let fn_parse_mode = FnParseMode {
1594 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1595 context: FnContext::Free,
1596 req_body: false,
1597 };
1598 Ok(self
1599 .parse_item_(
1600 fn_parse_mode,
1601 force_collect,
1602 AllowConstBlockItems::DoesNotMatter, )?
1604 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1605 let kind = match ForeignItemKind::try_from(kind) {
1606 Ok(kind) => kind,
1607 Err(kind) => match kind {
1608 ItemKind::Const(ConstItem { ident, ty, body, .. }) => {
1609 let const_span = Some(span.with_hi(ident.span.lo()))
1610 .filter(|span| span.can_be_used_for_suggestions());
1611 self.dcx().emit_err(diagnostics::ExternItemCannotBeConst {
1612 ident_span: ident.span,
1613 const_span,
1614 });
1615 ForeignItemKind::Static(Box::new(StaticItem {
1616 ident,
1617 ty,
1618 mutability: Mutability::Not,
1619 expr: body,
1620 safety: Safety::Default,
1621 define_opaque: None,
1622 eii_impl: None,
1623 }))
1624 }
1625 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1626 },
1627 };
1628 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1629 }))
1630 }
1631
1632 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1633 let span = self.psess.source_map().guess_head_span(span);
1635 let descr = kind.descr();
1636 let help = match kind {
1637 ItemKind::DelegationMac(DelegationMac {
1638 suffixes: DelegationSuffixes::Glob(_),
1639 ..
1640 }) => false,
1641 _ => true,
1642 };
1643 self.dcx().emit_err(diagnostics::BadItemKind { span, descr, ctx, help });
1644 None
1645 }
1646
1647 fn is_use_closure(&self) -> bool {
1648 if self.token.is_keyword(kw::Use) {
1649 self.look_ahead(1, |token| {
1651 let dist =
1653 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1654
1655 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))
1656 })
1657 } else {
1658 false
1659 }
1660 }
1661
1662 pub(super) fn is_unsafe_foreign_mod(&self) -> bool {
1663 if !self.token.is_keyword(kw::Unsafe) {
1665 return false;
1666 }
1667 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1669 return false;
1670 }
1671
1672 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1674
1675 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, _)))
1680 == Some(true)
1681 }
1682
1683 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1684 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) {
1685 !self.look_ahead(1, |token| {
1687 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1688 return true;
1689 }
1690 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1691 })
1692 } else {
1693 (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)
1695 || 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))
1696 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1697 };
1698
1699 if is_global_static {
1700 let safety = self.parse_safety(case);
1701 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);
1702 Some(safety)
1703 } else {
1704 None
1705 }
1706 }
1707
1708 fn recover_const_mut(&mut self, const_span: Span) {
1710 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)) {
1711 let span = self.prev_token.span;
1712 self.dcx()
1713 .emit_err(diagnostics::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1714 } 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)) {
1715 let span = self.prev_token.span;
1716 self.dcx()
1717 .emit_err(diagnostics::ConstLetMutuallyExclusive { span: const_span.to(span) });
1718 }
1719 }
1720
1721 fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
1722 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1723 let const_span = self.prev_token.span;
1724 self.psess.gated_spans.gate(sym::const_block_items, const_span);
1725 let block = self.parse_block()?;
1726 Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
1727 }
1728
1729 fn parse_static_item(
1736 &mut self,
1737 safety: Safety,
1738 mutability: Mutability,
1739 ) -> PResult<'a, ItemKind> {
1740 let ident = self.parse_ident()?;
1741
1742 if self.token == TokenKind::Lt && self.may_recover() {
1743 let generics = self.parse_generics()?;
1744 self.dcx().emit_err(diagnostics::StaticWithGenerics { span: generics.span });
1745 }
1746
1747 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))) {
1750 (true, false) => self.parse_ty()?,
1751 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1754 };
1755
1756 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 };
1757
1758 self.expect_semi()?;
1759
1760 let item =
1761 StaticItem { ident, ty, safety, mutability, expr, define_opaque: None, eii_impl: None };
1762 Ok(ItemKind::Static(Box::new(item)))
1763 }
1764
1765 fn parse_const_item(
1774 &mut self,
1775 const_span: Span,
1776 ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<Box<Expr>>)> {
1777 let ident = self.parse_ident_or_underscore()?;
1778
1779 let mut generics = self.parse_generics()?;
1780
1781 if !generics.span.is_empty() {
1784 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1785 }
1786
1787 let ty = match (
1790 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1791 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)),
1792 ) {
1793 (true, false) => self.parse_ty()?,
1794 (colon, _) => self.recover_missing_global_item_type(colon, None),
1796 };
1797
1798 let before_where_clause =
1801 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1802
1803 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 };
1804
1805 let after_where_clause = self.parse_where_clause()?;
1806
1807 if before_where_clause.has_where_token
1811 && let Some(rhs) = &rhs
1812 {
1813 self.dcx().emit_err(diagnostics::WhereClauseBeforeConstBody {
1814 span: before_where_clause.span,
1815 name: ident.span,
1816 body: rhs.span,
1817 sugg: if !after_where_clause.has_where_token {
1818 self.psess.source_map().span_to_snippet(rhs.span).ok().map(|body_s| {
1819 diagnostics::WhereClauseBeforeConstBodySugg {
1820 left: before_where_clause.span.shrink_to_lo(),
1821 snippet: body_s,
1822 right: before_where_clause.span.shrink_to_hi().to(rhs.span),
1823 }
1824 })
1825 } else {
1826 None
1829 },
1830 });
1831 }
1832
1833 let mut predicates = before_where_clause.predicates;
1840 predicates.extend(after_where_clause.predicates);
1841 let where_clause = WhereClause {
1842 has_where_token: before_where_clause.has_where_token
1843 || after_where_clause.has_where_token,
1844 predicates,
1845 span: if after_where_clause.has_where_token {
1846 after_where_clause.span
1847 } else {
1848 before_where_clause.span
1849 },
1850 };
1851
1852 if where_clause.has_where_token {
1853 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1854 }
1855
1856 generics.where_clause = where_clause;
1857
1858 if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
1859 return Ok((ident, generics, ty, Some(rhs)));
1860 }
1861 self.expect_semi()?;
1862
1863 Ok((ident, generics, ty, rhs))
1864 }
1865
1866 fn recover_missing_global_item_type(
1869 &mut self,
1870 colon_present: bool,
1871 m: Option<Mutability>,
1872 ) -> Box<Ty> {
1873 let kind = match m {
1876 Some(Mutability::Mut) => "static mut",
1877 Some(Mutability::Not) => "static",
1878 None => "const",
1879 };
1880
1881 let colon = match colon_present {
1882 true => "",
1883 false => ":",
1884 };
1885
1886 let span = self.prev_token.span.shrink_to_hi();
1887 let err = self.dcx().create_err(diagnostics::MissingConstType { span, colon, kind });
1888 err.stash(span, StashKey::ItemNoType);
1889
1890 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID })
1893 }
1894
1895 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1897 if self.token.is_keyword(kw::Struct) {
1898 let span = self.prev_token.span.to(self.token.span);
1899 let err = diagnostics::EnumStructMutuallyExclusive { span };
1900 if self.look_ahead(1, |t| t.is_ident()) {
1901 self.bump();
1902 self.dcx().emit_err(err);
1903 } else {
1904 return Err(self.dcx().create_err(err));
1905 }
1906 }
1907
1908 let prev_span = self.prev_token.span;
1909 let ident = self.parse_ident()?;
1910 let mut generics = self.parse_generics()?;
1911 generics.where_clause = self.parse_where_clause()?;
1912
1913 let (variants, _) = if self.token == TokenKind::Semi {
1915 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
1916 self.bump();
1917 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1918 } else {
1919 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| {
1920 p.parse_enum_variant(ident.span)
1921 })
1922 .map_err(|mut err| {
1923 err.span_label(ident.span, "while parsing this enum");
1924 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1926 let snapshot = self.create_snapshot_for_diagnostic();
1927 self.bump();
1928 match self.parse_ty() {
1929 Ok(_) => {
1930 err.span_suggestion_verbose(
1931 prev_span,
1932 "perhaps you meant to use `struct` here",
1933 "struct",
1934 Applicability::MaybeIncorrect,
1935 );
1936 }
1937 Err(e) => {
1938 e.cancel();
1939 }
1940 }
1941 self.restore_snapshot(snapshot);
1942 }
1943 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1944 self.bump(); err
1946 })?
1947 };
1948
1949 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1950 Ok(ItemKind::Enum(ident, generics, enum_definition))
1951 }
1952
1953 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1954 self.recover_vcs_conflict_marker();
1955 let variant_attrs = self.parse_outer_attributes()?;
1956 self.recover_vcs_conflict_marker();
1957 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1958 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1959 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1960 let vlo = this.token.span;
1961
1962 let vis = this.parse_visibility(FollowedByType::No)?;
1963 if !this.recover_nested_adt_item(kw::Enum)? {
1964 return Ok((None, Trailing::No, UsePreAttrPos::No));
1965 }
1966 let ident = this.parse_field_ident("enum", vlo)?;
1967
1968 if this.token == token::Bang {
1969 if let Err(err) = this.unexpected() {
1970 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();
1971 }
1972
1973 this.bump();
1974 this.parse_delim_args()?;
1975
1976 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1977 }
1978
1979 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)) {
1980 let (fields, recovered) =
1982 match this.parse_record_struct_body("struct", ident.span, false) {
1983 Ok((fields, recovered)) => (fields, recovered),
1984 Err(mut err) => {
1985 if this.token == token::Colon {
1986 return Err(err);
1988 }
1989 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1990 this.bump(); err.span_label(span, "while parsing this enum");
1992 err.help(help);
1993 let guar = err.emit_err();
1994 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1995 }
1996 };
1997 VariantData::Struct { fields, recovered }
1998 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1999 let body = match this.parse_tuple_struct_body() {
2000 Ok(body) => body,
2001 Err(mut err) => {
2002 if this.token == token::Colon {
2003 return Err(err);
2005 }
2006 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
2007 this.bump(); err.span_label(span, "while parsing this enum");
2009 err.help(help);
2010 err.emit();
2011 ::thin_vec::ThinVec::new()thin_vec![]
2012 }
2013 };
2014 VariantData::Tuple(body, DUMMY_NODE_ID)
2015 } else {
2016 VariantData::Unit(DUMMY_NODE_ID)
2017 };
2018
2019 let disr_expr =
2020 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 };
2021
2022 let span = vlo.to(this.prev_token.span);
2023 if ident.name == kw::Underscore {
2024 this.psess.gated_spans.gate(sym::unnamed_enum_variants, span);
2025 }
2026 let vr = ast::Variant {
2027 ident,
2028 vis,
2029 id: DUMMY_NODE_ID,
2030 attrs: variant_attrs,
2031 data: struct_def,
2032 disr_expr,
2033 span,
2034 is_placeholder: false,
2035 };
2036
2037 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
2038 })
2039 .map_err(|mut err| {
2040 err.help(help);
2041 err
2042 })
2043 }
2044
2045 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
2047 let ident = self.parse_ident()?;
2048
2049 let mut generics = self.parse_generics()?;
2050
2051 let vdata = if self.token.is_keyword(kw::Where) {
2066 let tuple_struct_body;
2067 (generics.where_clause, tuple_struct_body) =
2068 self.parse_struct_where_clause(ident, generics.span)?;
2069
2070 if let Some(body) = tuple_struct_body {
2071 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
2073 self.expect_semi()?;
2074 body
2075 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
2076 VariantData::Unit(DUMMY_NODE_ID)
2078 } else {
2079 let (fields, recovered) = self.parse_record_struct_body(
2081 "struct",
2082 ident.span,
2083 generics.where_clause.has_where_token,
2084 )?;
2085 VariantData::Struct { fields, recovered }
2086 }
2087 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
2089 VariantData::Unit(DUMMY_NODE_ID)
2090 } else if self.token == token::OpenBrace {
2092 let (fields, recovered) = self.parse_record_struct_body(
2093 "struct",
2094 ident.span,
2095 generics.where_clause.has_where_token,
2096 )?;
2097 VariantData::Struct { fields, recovered }
2098 } else if self.token == token::OpenParen {
2100 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
2101 generics.where_clause = self.parse_where_clause()?;
2102 self.expect_semi()?;
2103 body
2104 } else {
2105 let err = diagnostics::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
2106 return Err(self.dcx().create_err(err));
2107 };
2108
2109 Ok(ItemKind::Struct(ident, generics, vdata))
2110 }
2111
2112 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
2114 let ident = self.parse_ident()?;
2115
2116 let mut generics = self.parse_generics()?;
2117
2118 let vdata = if self.token.is_keyword(kw::Where) {
2119 generics.where_clause = self.parse_where_clause()?;
2120 let (fields, recovered) = self.parse_record_struct_body(
2121 "union",
2122 ident.span,
2123 generics.where_clause.has_where_token,
2124 )?;
2125 VariantData::Struct { fields, recovered }
2126 } else if self.token == token::OpenBrace {
2127 let (fields, recovered) = self.parse_record_struct_body(
2128 "union",
2129 ident.span,
2130 generics.where_clause.has_where_token,
2131 )?;
2132 VariantData::Struct { fields, recovered }
2133 } else {
2134 let token_str = super::token_descr(&self.token);
2135 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}");
2136 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2137 err.span_label(self.token.span, "expected `where` or `{` after union name");
2138 return Err(err);
2139 };
2140
2141 Ok(ItemKind::Union(ident, generics, vdata))
2142 }
2143
2144 pub(crate) fn parse_record_struct_body(
2149 &mut self,
2150 adt_ty: &str,
2151 ident_span: Span,
2152 parsed_where: bool,
2153 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
2154 let mut fields = ThinVec::new();
2155 let mut recovered = Recovered::No;
2156 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2157 while self.token != token::CloseBrace {
2158 match self.parse_field_def(adt_ty, ident_span) {
2159 Ok(field) => {
2160 fields.push(field);
2161 }
2162 Err(mut err) => {
2163 self.consume_block(
2164 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
2165 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
2166 ConsumeClosingDelim::No,
2167 );
2168 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}"));
2169 let guar = err.emit_err();
2170 recovered = Recovered::Yes(guar);
2171 break;
2172 }
2173 }
2174 }
2175 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
2176 } else {
2177 let token_str = super::token_descr(&self.token);
2178 let where_str = if parsed_where { "" } else { "`where`, or " };
2179 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}");
2180 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2181 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",));
2182 return Err(err);
2183 }
2184
2185 Ok((fields, recovered))
2186 }
2187
2188 fn parse_unsafe_field(&mut self) -> Safety {
2189 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)) {
2191 let span = self.prev_token.span;
2192 self.psess.gated_spans.gate(sym::unsafe_fields, span);
2193 Safety::Unsafe(span)
2194 } else {
2195 Safety::Default
2196 }
2197 }
2198 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
2201 let openparen_span = self.token.span;
2202 let mut encountered_colon = false;
2203 self.parse_paren_comma_seq(|p| {
2204 let attrs = p.parse_outer_attributes()?;
2205 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
2206 let mut snapshot = None;
2207 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
2208 snapshot = Some(p.create_snapshot_for_diagnostic());
2212 }
2213 let lo = p.token.span;
2214 let vis = match p.parse_visibility(FollowedByType::Yes) {
2215 Ok(vis) => vis,
2216 Err(err) => {
2217 if let Some(ref mut snapshot) = snapshot {
2218 snapshot.recover_vcs_conflict_marker();
2219 }
2220 return Err(err);
2221 }
2222 };
2223 let mut_restriction = p.parse_mut_restriction()?;
2224 encountered_colon |=
2225 p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
2226 let ty = match p.parse_ty() {
2229 Ok(ty) => ty,
2230 Err(err) => {
2231 if let Some(ref mut snapshot) = snapshot {
2232 snapshot.recover_vcs_conflict_marker();
2233 }
2234 return Err(err);
2235 }
2236 };
2237 let mut default = None;
2238 if p.token == token::Eq {
2239 let mut snapshot = p.create_snapshot_for_diagnostic();
2240 snapshot.bump();
2241 match snapshot.parse_expr_anon_const() {
2242 Ok(const_expr) => {
2243 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2244 p.psess.gated_spans.gate(sym::default_field_values, sp);
2245 p.restore_snapshot(snapshot);
2246 default = Some(const_expr);
2247 }
2248 Err(err) => {
2249 err.cancel();
2250 }
2251 }
2252 }
2253
2254 Ok((
2255 FieldDef {
2256 span: lo.to(ty.span),
2257 vis,
2258 extras: Self::field_def_extras(Safety::Default, mut_restriction, default),
2259 ident: None,
2260 id: DUMMY_NODE_ID,
2261 ty,
2262 attrs,
2263 is_placeholder: false,
2264 },
2265 Trailing::from(p.token == token::Comma),
2266 UsePreAttrPos::No,
2267 ))
2268 })
2269 })
2270 .map(|(r, _)| r)
2271 .map_err(|mut error| {
2272 if self.token == token::Colon {
2273 error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
2274 }
2275 if encountered_colon {
2276 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
2277 self.bump();
2278 error.subdiagnostic(UseRegularStructSuggestion {
2279 open: openparen_span,
2280 close: self.prev_token.span,
2281 semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
2282 });
2283 }
2284 error
2285 })
2286 }
2287
2288 fn field_def_extras(
2289 safety: Safety,
2290 mut_restriction: MutRestriction,
2291 default: Option<AnonConst>,
2292 ) -> Option<Box<FieldDefExtras>> {
2293 match (safety, mut_restriction, default) {
2294 (
2295 Safety::Default,
2296 MutRestriction { kind: RestrictionKind::Unrestricted, span: _ },
2299 None,
2300 ) => None,
2301 (safety, mut_restriction, default) => {
2302 Some(Box::new(FieldDefExtras { safety, mut_restriction, default }))
2303 }
2304 }
2305 }
2306
2307 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2309 self.recover_vcs_conflict_marker();
2310 let attrs = self.parse_outer_attributes()?;
2311 self.recover_vcs_conflict_marker();
2312 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2313 let lo = this.token.span;
2314 let vis = this.parse_visibility(FollowedByType::No)?;
2315 let mut_restriction = this.parse_mut_restriction()?;
2316 let safety = this.parse_unsafe_field();
2317 this.parse_single_struct_field(
2318 adt_ty,
2319 lo,
2320 vis,
2321 mut_restriction,
2322 safety,
2323 attrs,
2324 ident_span,
2325 )
2326 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2327 })
2328 }
2329
2330 fn parse_single_struct_field(
2332 &mut self,
2333 adt_ty: &str,
2334 lo: Span,
2335 vis: Visibility,
2336 mut_restriction: MutRestriction,
2337 safety: Safety,
2338 attrs: AttrVec,
2339 ident_span: Span,
2340 ) -> PResult<'a, FieldDef> {
2341 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, mut_restriction, safety, attrs)?;
2342 match self.token.kind {
2343 token::Comma => {
2344 self.bump();
2345 }
2346 token::Semi => {
2347 self.bump();
2348 let sp = self.prev_token.span;
2349 let mut err =
2350 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 `,`"));
2351 err.span_suggestion_short(
2352 sp,
2353 "replace `;` with `,`",
2354 ",",
2355 Applicability::MachineApplicable,
2356 );
2357 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}"));
2358 err.emit();
2359 }
2360 token::CloseBrace => {}
2361 token::DocComment(..) => {
2362 let previous_span = self.prev_token.span;
2363 let mut err = diagnostics::DocCommentDoesNotDocumentAnything {
2364 span: self.token.span,
2365 missing_comma: None,
2366 };
2367 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 {
2369 self.dcx().emit_err(err);
2370 } else {
2371 let sp = previous_span.shrink_to_hi();
2372 err.missing_comma = Some(sp);
2373 return Err(self.dcx().create_err(err));
2374 }
2375 }
2376 _ => {
2377 let sp = self.prev_token.span.shrink_to_hi();
2378 let msg =
2379 ::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));
2380
2381 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2383 && let Some(last_segment) = segments.last()
2384 {
2385 let guar = self.check_trailing_angle_brackets(
2386 last_segment,
2387 &[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)],
2388 );
2389 if let Some(_guar) = guar {
2390 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2393
2394 return Ok(a_var);
2397 }
2398 }
2399
2400 let mut err = self.dcx().struct_span_err(sp, msg);
2401
2402 if self.token.is_ident()
2403 || (self.token == TokenKind::Pound
2404 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2405 {
2406 err.span_suggestion(
2409 sp,
2410 "try adding a comma",
2411 ",",
2412 Applicability::MachineApplicable,
2413 );
2414 err.emit();
2415 } else {
2416 return Err(err);
2417 }
2418 }
2419 }
2420 Ok(a_var)
2421 }
2422
2423 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2424 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)) {
2425 let sm = self.psess.source_map();
2426 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2427 let semi_typo = self.token == token::Semi
2428 && self.look_ahead(1, |t| {
2429 t.is_path_start()
2430 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2433 (Ok(l), Ok(r)) => l.line == r.line,
2434 _ => true,
2435 }
2436 });
2437 if eq_typo || semi_typo {
2438 self.bump();
2439 err.with_span_suggestion_short(
2441 self.prev_token.span,
2442 "field names and their types are separated with `:`",
2443 ":",
2444 Applicability::MachineApplicable,
2445 )
2446 .emit();
2447 } else {
2448 return Err(err);
2449 }
2450 }
2451 Ok(())
2452 }
2453
2454 fn parse_name_and_ty(
2456 &mut self,
2457 adt_ty: &str,
2458 lo: Span,
2459 vis: Visibility,
2460 mut_restriction: MutRestriction,
2461 safety: Safety,
2462 attrs: AttrVec,
2463 ) -> PResult<'a, FieldDef> {
2464 let name = self.parse_field_ident(adt_ty, lo)?;
2465 if self.token == token::Bang {
2466 if let Err(mut err) = self.unexpected() {
2467 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2469 return Err(err);
2470 }
2471 }
2472 self.expect_field_ty_separator()?;
2473 let ty = self.parse_ty()?;
2474 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2475 return Err(self
2476 .dcx()
2477 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2478 .with_span_suggestion_verbose(
2479 self.token.span,
2480 "write a path separator here",
2481 "::",
2482 Applicability::MaybeIncorrect,
2483 ));
2484 }
2485 let default = if self.token == token::Eq {
2486 self.bump();
2487 let const_expr = self.parse_expr_anon_const()?;
2488 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2489 self.psess.gated_spans.gate(sym::default_field_values, sp);
2490 Some(const_expr)
2491 } else {
2492 None
2493 };
2494 Ok(FieldDef {
2495 span: lo.to(self.prev_token.span),
2496 ident: Some(name),
2497 vis,
2498 extras: Self::field_def_extras(safety, mut_restriction, default),
2499 id: DUMMY_NODE_ID,
2500 ty,
2501 attrs,
2502 is_placeholder: false,
2503 })
2504 }
2505
2506 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2509 let (ident, kind) = self.ident_or_err(true)?;
2510 if kind == IdentKind::Normal
2511 && ident.is_reserved()
2512 && !(ident.name == kw::Underscore && adt_ty == "enum")
2513 {
2514 let snapshot = self.create_snapshot_for_diagnostic();
2515 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2516 let inherited_vis = Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited };
2517 let fn_parse_mode =
2519 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2520 match self.parse_fn(
2521 &mut AttrVec::new(),
2522 fn_parse_mode,
2523 lo,
2524 &inherited_vis,
2525 Case::Insensitive,
2526 ) {
2527 Ok(_) => self
2528 .dcx()
2529 .struct_span_err(
2530 lo.to(self.prev_token.span),
2531 ::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"),
2532 )
2533 .with_help(
2534 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2535 )
2536 .with_help(
2537 "see https://doc.rust-lang.org/book/ch05-03-method-syntax.html \
2538 for more information",
2539 ),
2540 Err(err) => {
2541 err.cancel();
2542 self.restore_snapshot(snapshot);
2543 self.expected_ident_found_err()
2544 }
2545 }
2546 } 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)) {
2547 match self.parse_item_struct() {
2548 Ok(item) => {
2549 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2550 self.dcx()
2551 .struct_span_err(
2552 lo.with_hi(ident.span.hi()),
2553 ::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"),
2554 )
2555 .with_help(
2556 "consider creating a new `struct` definition instead of nesting",
2557 )
2558 }
2559 Err(err) => {
2560 err.cancel();
2561 self.restore_snapshot(snapshot);
2562 self.expected_ident_found_err()
2563 }
2564 }
2565 } else {
2566 let mut err = self.expected_ident_found_err();
2567 if self.eat_keyword_noexpect(kw::Let)
2568 && let removal_span = self.prev_token.span.until(self.token.span)
2569 && let Ok(ident) = self
2570 .parse_ident_common(false)
2571 .map_err(|err| err.cancel())
2573 && self.token == TokenKind::Colon
2574 {
2575 err.span_suggestion_verbose(
2576 removal_span,
2577 "remove the `let` keyword",
2578 String::new(),
2579 Applicability::MachineApplicable,
2580 );
2581 err.note("the `let` keyword is not allowed in `struct` fields");
2582 err.note(
2583 "see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> \
2584 for more information",
2585 );
2586 err.emit();
2587 return Ok(ident);
2588 } else {
2589 self.restore_snapshot(snapshot);
2590 }
2591 err
2592 };
2593 return Err(err);
2594 }
2595 self.bump();
2596 Ok(ident)
2597 }
2598
2599 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2607 let ident = self.parse_ident()?;
2608 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)) {
2609 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)) {
2611 let params = self.parse_token_tree(); let pspan = params.span();
2613 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2614 self.unexpected()?;
2615 }
2616 let body = self.parse_token_tree(); let bspan = body.span();
2619 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]);
2621 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2622 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2623 } else {
2624 self.unexpected_any()?
2625 };
2626
2627 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2628 Ok(ItemKind::MacroDef(
2629 ident,
2630 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2631 ))
2632 }
2633
2634 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2636 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)) {
2637 let macro_rules_span = self.token.span;
2638
2639 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2640 return IsMacroRulesItem::Yes { has_bang: true };
2641 } else if self.look_ahead(1, |t| t.is_ident()) {
2642 self.dcx().emit_err(diagnostics::MacroRulesMissingBang {
2644 span: macro_rules_span,
2645 hi: macro_rules_span.shrink_to_hi(),
2646 });
2647
2648 return IsMacroRulesItem::Yes { has_bang: false };
2649 }
2650 }
2651
2652 IsMacroRulesItem::No
2653 }
2654
2655 fn parse_item_macro_rules(
2657 &mut self,
2658 vis: &Visibility,
2659 has_bang: bool,
2660 ) -> PResult<'a, ItemKind> {
2661 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 {
2664 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2666 let ident = self.parse_ident()?;
2667
2668 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2669 let span = self.prev_token.span;
2671 self.dcx().emit_err(diagnostics::MacroNameRemoveBang { span });
2672 }
2673
2674 let body = self.parse_delim_args()?;
2675 self.eat_semi_for_macro_if_needed(&body, None);
2676 self.complain_if_pub_macro(vis, true);
2677
2678 Ok(ItemKind::MacroDef(
2679 ident,
2680 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2681 ))
2682 }
2683
2684 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2687 if let VisibilityKind::Inherited = vis.kind {
2688 return;
2689 }
2690
2691 let vstr = pprust::vis_to_string(vis);
2692 let vstr = vstr.trim_end();
2693 if macro_rules {
2694 self.dcx().emit_err(diagnostics::MacroRulesVisibility { span: vis.span, vis: vstr });
2695 } else {
2696 self.dcx()
2697 .emit_err(diagnostics::MacroInvocationVisibility { span: vis.span, vis: vstr });
2698 }
2699 }
2700
2701 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
2702 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)) {
2703 self.report_invalid_macro_expansion_item(args, path);
2704 }
2705 }
2706
2707 pub fn parse_test_binder_constraints(&mut self) -> PResult<'a, Box<TestBinderConstraints>> {
2709 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
2710 let mut generics = self.parse_generics()?;
2711 generics.where_clause = self.parse_where_clause()?;
2712 let body = self.parse_test_binder_body()?;
2713 Ok(Box::new(TestBinderConstraints { generics, body: Box::new(body) }))
2714 }
2715
2716 pub fn parse_test_binder_body(&mut self) -> PResult<'a, TestBinderBody> {
2717 let mut foralls = ThinVec::new();
2718 let mut exists = ThinVec::new();
2719 let mut constraints = Vec::new();
2720 let mut predicates = Vec::new();
2721 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), |this| {
2722 if this.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Where,
token_type: crate::parser::token_type::TokenType::KwWhere,
}exp!(Where)) {
2723 predicates.push(this.parse_where_clause()?);
2724 return Ok(());
2725 }
2726 match this.token.ident() {
2727 Some((Ident { name: sym::forall, .. }, IdentKind::Normal)) => {
2728 foralls.push(this.parse_test_binder_forall()?)
2729 }
2730 Some((Ident { name: sym::exists, .. }, IdentKind::Normal)) => {
2731 exists.push(this.parse_test_binder_exists()?)
2732 }
2733
2734 _ => constraints.push(this.parse_test_binder_constraint()?),
2735 }
2736 Ok(())
2737 })?;
2738 Ok(TestBinderBody { foralls, exists, constraints, predicates })
2739 }
2740
2741 pub fn parse_test_binder_forall(&mut self) -> PResult<'a, TestBinderForall> {
2742 let span = self.token.span;
2743 self.bump();
2744
2745 let mut generics = self.parse_generics()?;
2746 generics.where_clause = self.parse_where_clause()?;
2747
2748 let body = self.parse_test_binder_body()?;
2749
2750 let assert_on_exit = if let Some((i, IdentKind::Normal)) = self.token.ident()
2751 && i.name == sym::expect
2752 {
2753 self.bump();
2754 let items = self
2755 .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), |this| {
2756 this.parse_test_binder_constraint()
2757 })?
2758 .0;
2759 Some(items)
2760 } else {
2761 None
2762 };
2763
2764 Ok(TestBinderForall { span, node_id: DUMMY_NODE_ID, generics, body, assert_on_exit })
2765 }
2766
2767 pub fn parse_test_binder_exists(&mut self) -> PResult<'a, TestBinderExists> {
2768 let span = self.token.span;
2769 self.bump();
2770 let params = self.parse_generics()?.params;
2771 let body = self.parse_test_binder_body()?;
2772 Ok(TestBinderExists { span, node_id: DUMMY_NODE_ID, params, body })
2773 }
2774
2775 pub fn parse_test_binder_constraint(&mut self) -> PResult<'a, TestBinderConstraint> {
2776 match self.token.ident() {
2777 Some((Ident { name: sym::and, .. }, IdentKind::Normal)) => {
2778 self.bump();
2779 let items = self
2780 .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), |this| {
2781 this.parse_test_binder_constraint()
2782 })?
2783 .0;
2784 Ok(TestBinderConstraint::And { items })
2785 }
2786 Some((Ident { name: sym::or, .. }, IdentKind::Normal)) => {
2787 self.bump();
2788 let items = self
2789 .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), |this| {
2790 this.parse_test_binder_constraint()
2791 })?
2792 .0;
2793 Ok(TestBinderConstraint::Or { items })
2794 }
2795 _ if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::For,
token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For)) => {
2796 let bound_type_constraint = self.parse_test_binder_bound_type_constraint()?;
2797 Ok(TestBinderConstraint::AliasOutlives { bound_type_constraint })
2798 }
2799 _ if self.token.lifetime().is_some() => {
2800 let lhs = self.expect_lifetime();
2801 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon))?;
2802 if !self.check_lifetime() {
2803 self.unexpected()?;
2804 }
2805 let rhs = self.expect_lifetime();
2806 Ok(TestBinderConstraint::Lifetime { lhs, rhs })
2807 }
2808 _ if self.token.can_begin_type() => {
2809 let lhs = self.parse_ty_for_where_clause()?;
2810 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon))?;
2811 if !self.check_lifetime() {
2812 self.unexpected()?;
2813 }
2814 let rhs = self.expect_lifetime();
2815 Ok(TestBinderConstraint::PlaceholderOutlives { lhs, rhs })
2816 }
2817 _ => Err(self.dcx().struct_span_err(self.token.span, "unexpected token")),
2818 }
2819 }
2820
2821 fn parse_test_binder_bound_type_constraint(
2822 &mut self,
2823 ) -> PResult<'a, TestBinderBoundTypeConstraint> {
2824 let lo = self.token.span;
2825 let ast::WhereBoundPredicate { bound_generic_params, bounded_ty, bounds } =
2826 self.parse_ty_where_predicate_kind()?;
2827 let mut rhs = None;
2828 for bound in bounds {
2829 match bound {
2830 GenericBound::Trait(poly_trait_ref) => {
2831 self.dcx().span_err(poly_trait_ref.span, "trait bounds aren't supported here");
2832 }
2833 GenericBound::Use(_, span) => {
2834 self.dcx().span_err(span, "use bounds aren't supported here");
2835 }
2836 GenericBound::Outlives(lifetime) => {
2837 if rhs.is_some() {
2838 self.dcx().span_err(
2839 lifetime.ident.span,
2840 "only one lifetime on the rhs supported",
2841 );
2842 } else {
2843 rhs = Some(lifetime);
2844 }
2845 }
2846 }
2847 }
2848 match rhs {
2849 Some(rhs) => Ok(TestBinderBoundTypeConstraint {
2850 span: lo.to(self.prev_token.span),
2851 node_id: DUMMY_NODE_ID,
2852 params: bound_generic_params,
2853 lhs: bounded_ty,
2854 rhs,
2855 }),
2856 None => Err(self.dcx().struct_span_err(
2857 bounded_ty.span,
2858 "expected a single lifetime on the rhs of this constraint",
2859 )),
2860 }
2861 }
2862
2863 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
2864 let span = args.dspan.entire();
2865 let mut err = self.dcx().struct_span_err(
2866 span,
2867 "macros that expand to items must be delimited with braces or followed by a semicolon",
2868 );
2869 if !span.from_expansion() {
2872 let DelimSpan { open, close } = args.dspan;
2873 if let Some(path) = path
2876 && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2877 && args.delim == Delimiter::Parenthesis
2878 {
2879 let replace =
2880 if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2881 err.multipart_suggestion(
2882 "to define a macro, remove the parentheses around the macro name",
2883 ::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())],
2884 Applicability::MachineApplicable,
2885 );
2886 } else {
2887 err.multipart_suggestion(
2888 "change the delimiters to curly braces",
2889 ::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())],
2890 Applicability::MaybeIncorrect,
2891 );
2892 err.span_suggestion_verbose(
2893 span.with_neighbor(self.token.span).shrink_to_hi(),
2894 "add a semicolon",
2895 ';',
2896 Applicability::MaybeIncorrect,
2897 );
2898 }
2899 }
2900 err.emit();
2901 }
2902
2903 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2906 if (self.token.is_keyword(kw::Enum)
2907 || self.token.is_keyword(kw::Struct)
2908 || self.token.is_keyword(kw::Union))
2909 && self.look_ahead(1, |t| t.is_ident())
2910 {
2911 let kw_token = self.token;
2912 let kw_str = pprust::token_to_string(&kw_token);
2913 let item = self.parse_item(
2914 ForceCollect::No,
2915 AllowConstBlockItems::DoesNotMatter, )?;
2917 let mut item = item.unwrap().span;
2918 if self.token == token::Comma {
2919 item = item.to(self.token.span);
2920 }
2921 self.dcx().emit_err(diagnostics::NestedAdt {
2922 span: kw_token.span,
2923 item,
2924 kw_str,
2925 keyword: keyword.as_str(),
2926 });
2927 return Ok(false);
2929 }
2930 Ok(true)
2931 }
2932
2933 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2934 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2935 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)) {
2938 return true;
2939 }
2940 let mut i = 0;
2941 while i < ALL_QUALS.len() {
2942 let action = self.look_ahead(i + look_ahead, |token| {
2943 if token.is_keyword(kw::Impl) {
2944 return Some(true);
2945 }
2946 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2947 return None;
2949 }
2950 Some(false)
2951 });
2952 if let Some(ret) = action {
2953 return ret;
2954 }
2955 i += 1;
2956 }
2957
2958 self.is_keyword_ahead(i, &[kw::Impl])
2959 }
2960
2961 fn try_recover_const_missing_semi(
2969 &mut self,
2970 rhs: &Option<Box<Expr>>,
2971 const_span: Span,
2972 ) -> Option<Box<Expr>> {
2973 if self.token == TokenKind::Semi {
2974 return None;
2975 }
2976 let Some(rhs) = rhs else {
2977 return None;
2978 };
2979 if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
2980 return None;
2981 }
2982 if let Some((span, guar)) =
2983 self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
2984 {
2985 self.fn_body_missing_semi_guar = Some(guar);
2986 Some(self.mk_expr(span, ExprKind::Err(guar)))
2987 } else {
2988 None
2989 }
2990 }
2991}
2992
2993enum IsMacroRulesItem {
2994 Yes { has_bang: bool },
2995 No,
2996}
2997
2998struct UsePathList<'a> {
2999 elements: &'a [ast::PathSegment],
3000 prev: Option<&'a Self>,
3001}