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