1use std::fmt::Write;
2use std::mem;
3
4use ast::token::IdentIsRaw;
5use rustc_ast as ast;
6use rustc_ast::ast::*;
7use rustc_ast::token::{self, Delimiter, MetaVarKind, TokenKind};
8use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
9use rustc_ast::util::case::Case;
10use rustc_ast_pretty::pprust;
11use rustc_errors::codes::*;
12use rustc_errors::{Applicability, PResult, StashKey, msg, struct_span_code_err};
13use rustc_span::edit_distance::edit_distance;
14use rustc_span::edition::Edition;
15use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
16use thin_vec::{ThinVec, thin_vec};
17use tracing::debug;
18
19use super::diagnostics::ConsumeClosingDelim;
20use super::{
21 AllowConstBlockItems, AttrWrapper, ExpTokenPair, FnContext, FnParseMode, FollowedByType,
22 ForceCollect, IsDotDotDot, Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,
23};
24use crate::diagnostics::{
25 self, MacroExpandsToAdtField, UseDoubleColonSuggestion, UseRegularStructSuggestion,
26};
27use crate::exp;
28
29impl<'a> Parser<'a> {
30 pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
32 let (attrs, items, spans) = self.parse_mod(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eof,
token_type: crate::parser::token_type::TokenType::Eof,
}exp!(Eof))?;
33 Ok(ast::Crate { attrs, items, spans, id: DUMMY_NODE_ID, is_placeholder: false })
34 }
35
36 fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
38 let safety = self.parse_safety(Case::Sensitive);
39 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mod,
token_type: crate::parser::token_type::TokenType::KwMod,
}exp!(Mod))?;
40 let ident = self.parse_ident()?;
41 let mod_kind = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
42 ModKind::Unloaded
43 } else {
44 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
45 let (inner_attrs, items, inner_span) = self.parse_mod(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
46 attrs.extend(inner_attrs);
47 ModKind::Loaded(items, Inline::Yes, inner_span)
48 };
49 Ok(ItemKind::Mod(safety, ident, mod_kind))
50 }
51
52 pub fn parse_mod(
57 &mut self,
58 term: ExpTokenPair,
59 ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
60 let lo = self.token.span;
61 let attrs = self.parse_inner_attributes()?;
62
63 let post_attr_lo = self.token.span;
64 let mut items: ThinVec<Box<_>> = ThinVec::new();
65
66 loop {
69 while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else {
71 break;
72 };
73 items.push(item);
74 }
75
76 if !self.eat(term) {
77 let token_str = super::token_descr(&self.token);
78 if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
79 let is_let = self.token.is_keyword(kw::Let);
80 let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
81 let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);
82
83 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected item, found {0}",
token_str))
})format!("expected item, found {token_str}");
84 let mut err = self.dcx().struct_span_err(self.token.span, msg);
85
86 let label = if is_let {
87 "`let` cannot be used for global variables"
88 } else {
89 "expected item"
90 };
91 err.span_label(self.token.span, label);
92
93 if is_let {
94 if is_let_mut {
95 err.help("consider using `static` and a `Mutex` instead of `let mut`");
96 } else if let_has_ident {
97 err.span_suggestion_short(
98 self.token.span,
99 "consider using `static` or `const` instead of `let`",
100 "static",
101 Applicability::MaybeIncorrect,
102 );
103 } else {
104 err.help("consider using `static` or `const` instead of `let`");
105 }
106 }
107 err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
108 return Err(err);
109 }
110 }
111
112 let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo());
113 let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };
114 Ok((attrs, items, mod_spans))
115 }
116}
117
118enum ReuseKind {
119 Path,
120 Impl,
121}
122
123impl<'a> Parser<'a> {
124 pub fn parse_item(
125 &mut self,
126 force_collect: ForceCollect,
127 allow_const_block_items: AllowConstBlockItems,
128 ) -> PResult<'a, Option<Box<Item>>> {
129 let fn_parse_mode =
130 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
131 self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items)
132 .map(|i| i.map(Box::new))
133 }
134
135 fn parse_item_(
136 &mut self,
137 fn_parse_mode: FnParseMode,
138 force_collect: ForceCollect,
139 const_block_items_allowed: AllowConstBlockItems,
140 ) -> PResult<'a, Option<Item>> {
141 self.recover_vcs_conflict_marker();
142 let attrs = self.parse_outer_attributes()?;
143 self.recover_vcs_conflict_marker();
144 self.parse_item_common(
145 attrs,
146 true,
147 false,
148 fn_parse_mode,
149 force_collect,
150 const_block_items_allowed,
151 )
152 }
153
154 pub(super) fn parse_item_common(
155 &mut self,
156 attrs: AttrWrapper,
157 mac_allowed: bool,
158 attrs_allowed: bool,
159 fn_parse_mode: FnParseMode,
160 force_collect: ForceCollect,
161 allow_const_block_items: AllowConstBlockItems,
162 ) -> PResult<'a, Option<Item>> {
163 if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| {
164 this.parse_item(ForceCollect::Yes, allow_const_block_items)
165 }) {
166 let mut item = item.expect("an actual item");
167 attrs.prepend_to_nt_inner(&mut item.attrs);
168 return Ok(Some(*item));
169 }
170
171 self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {
172 let lo = this.token.span;
173 let vis = this.parse_visibility(FollowedByType::No)?;
174 let mut def = this.parse_defaultness();
175 let kind = this.parse_item_kind(
176 &mut attrs,
177 mac_allowed,
178 allow_const_block_items,
179 lo,
180 &vis,
181 &mut def,
182 fn_parse_mode,
183 Case::Sensitive,
184 )?;
185 if let Some(kind) = kind {
186 this.error_on_unconsumed_default(def, &kind);
187 let span = lo.to(this.prev_token.span);
188 let id = DUMMY_NODE_ID;
189 let item = Item { attrs, id, kind, vis, span, tokens: None };
190 return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
191 }
192
193 if !#[allow(non_exhaustive_omitted_patterns)] match vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(vis.kind, VisibilityKind::Inherited) {
195 let vis_str = pprust::vis_to_string(&vis).trim_end().to_string();
196 let mut err = this.dcx().create_err(diagnostics::VisibilityNotFollowedByItem {
197 span: vis.span,
198 vis: vis_str,
199 });
200 if let Some((ident, _)) = this.token.ident()
201 && !ident.is_used_keyword()
202 && let Some((similar_kw, is_incorrect_case)) = ident
203 .name
204 .find_similar(&rustc_span::symbol::used_keywords(|| ident.span.edition()))
205 {
206 err.subdiagnostic(diagnostics::MisspelledKw {
207 similar_kw: similar_kw.to_string(),
208 span: ident.span,
209 is_incorrect_case,
210 });
211 }
212 err.emit();
213 }
214
215 if let Defaultness::Default(span) = def {
216 this.dcx().emit_err(diagnostics::DefaultNotFollowedByItem { span });
217 } else if let Defaultness::Final(span) = def {
218 this.dcx().emit_err(diagnostics::FinalNotFollowedByItem { span });
219 }
220
221 if !attrs_allowed {
222 this.recover_attrs_no_item(&attrs)?;
223 }
224 Ok((None, Trailing::No, UsePreAttrPos::No))
225 })
226 }
227
228 fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
230 match def {
231 Defaultness::Default(span) => {
232 self.dcx().emit_err(diagnostics::InappropriateDefault {
233 span,
234 article: kind.article(),
235 descr: kind.descr(),
236 });
237 }
238 Defaultness::Final(span) => {
239 self.dcx().emit_err(diagnostics::InappropriateFinal {
240 span,
241 article: kind.article(),
242 descr: kind.descr(),
243 });
244 }
245 Defaultness::Implicit => (),
246 }
247 }
248
249 fn parse_item_kind(
251 &mut self,
252 attrs: &mut AttrVec,
253 macros_allowed: bool,
254 allow_const_block_items: AllowConstBlockItems,
255 lo: Span,
256 vis: &Visibility,
257 def: &mut Defaultness,
258 fn_parse_mode: FnParseMode,
259 case: Case,
260 ) -> PResult<'a, Option<ItemKind>> {
261 let check_pub = def == &Defaultness::Implicit;
262 let mut def_ = || mem::replace(def, Defaultness::Implicit);
263
264 let info = if !self.is_use_closure() && self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Use,
token_type: crate::parser::token_type::TokenType::KwUse,
}exp!(Use), case) {
265 self.parse_use_item()?
266 } else if self.check_fn_front_matter(check_pub, case) {
267 let defaultness = def_();
269 if let Defaultness::Default(span) = defaultness {
270 self.psess.gated_spans.gate(sym::min_specialization, span);
274 self.psess.gated_spans.ungate_last(sym::specialization, span);
275 }
276 let (ident, sig, generics, contract, body) =
277 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
278 ItemKind::Fn(Box::new(Fn {
279 defaultness,
280 ident,
281 sig,
282 generics,
283 contract,
284 body,
285 define_opaque: None,
286 eii_impl: None,
287 }))
288 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern), case) {
289 if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Crate,
token_type: crate::parser::token_type::TokenType::KwCrate,
}exp!(Crate), case) {
290 self.parse_item_extern_crate()?
292 } else {
293 self.parse_item_foreign_mod(attrs, Safety::Default)?
295 }
296 } else if self.is_unsafe_foreign_mod() {
297 let safety = self.parse_safety(Case::Sensitive);
299 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern))?;
300 self.parse_item_foreign_mod(attrs, safety)?
301 } else if let Some(safety) = self.parse_global_static_front_matter(case) {
302 let mutability = self.parse_mutability();
304 self.parse_static_item(safety, mutability)?
305 } else if self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait), case) || self.check_trait_front_matter() {
306 self.parse_item_trait(attrs, lo)?
308 } else if self.check_impl_frontmatter(0) {
309 self.parse_item_impl(attrs, def_(), false)?
311 } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
312 allow_const_block_items
313 && self.check_inline_const(0)
314 {
315 if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
317 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_parse/src/parser/item.rs:317",
"rustc_parse::parser::item", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_parse/src/parser/item.rs"),
::tracing_core::__macro_support::Option::Some(317u32),
::tracing_core::__macro_support::Option::Some("rustc_parse::parser::item"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Parsing a const block item that does not matter: {0:?}",
self.token.span) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("Parsing a const block item that does not matter: {:?}", self.token.span);
318 };
319 ItemKind::ConstBlock(self.parse_const_block_item()?)
320 } else if let Const::Yes(const_span) = self.parse_constness(case) {
321 self.recover_const_mut(const_span);
323 self.recover_missing_kw_before_item()?;
324 let (ident, generics, ty, body) = self.parse_const_item(const_span)?;
325 ItemKind::Const(Box::new(ConstItem {
326 defaultness: def_(),
327 ident,
328 generics,
329 ty,
330 body,
331 kind: ConstItemKind::Body,
332 define_opaque: None,
333 }))
334 } else if let Some(kind) = self.is_reuse_item() {
335 self.parse_item_delegation(attrs, def_(), kind)?
336 } 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)
337 || 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])
338 {
339 self.parse_item_mod(attrs)?
341 } 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) {
342 if let Const::Yes(const_span) = self.parse_constness(case) {
343 self.recover_const_mut(const_span);
345 self.recover_missing_kw_before_item()?;
346 let (ident, generics, ty, body) = self.parse_const_item(const_span)?;
347 self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span));
350 ItemKind::Const(Box::new(ConstItem {
351 defaultness: def_(),
352 ident,
353 generics,
354 ty,
355 body,
356 kind: ConstItemKind::TypeConst,
357 define_opaque: None,
358 }))
359 } else {
360 self.parse_type_alias(def_())?
362 }
363 } 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) {
364 self.parse_item_enum()?
366 } 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) {
367 self.parse_item_struct()?
369 } else if self.is_kw_followed_by_ident(kw::Union) {
370 self.bump(); self.parse_item_union()?
373 } else if self.is_builtin() {
374 return self.parse_item_builtin();
376 } 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) {
377 self.parse_item_decl_macro(lo)?
379 } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
380 self.parse_item_macro_rules(vis, has_bang)?
382 } else if self.isnt_macro_invocation()
383 && (self.token.is_ident_named(sym::import)
384 || self.token.is_ident_named(sym::using)
385 || self.token.is_ident_named(sym::include)
386 || self.token.is_ident_named(sym::require))
387 {
388 return self.recover_import_as_use();
389 } else if self.isnt_macro_invocation() && vis.kind.is_pub() {
390 self.recover_missing_kw_before_item()?;
391 return Ok(None);
392 } else if self.isnt_macro_invocation() && case == Case::Sensitive {
393 _ = def_;
394
395 return self.parse_item_kind(
397 attrs,
398 macros_allowed,
399 allow_const_block_items,
400 lo,
401 vis,
402 def,
403 fn_parse_mode,
404 Case::Insensitive,
405 );
406 } else if macros_allowed && self.check_path() {
407 if self.isnt_macro_invocation() {
408 self.recover_missing_kw_before_item()?;
409 }
410 ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
412 } else {
413 return Ok(None);
414 };
415 Ok(Some(info))
416 }
417
418 fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
419 let span = self.token.span;
420 let token_name = super::token_descr(&self.token);
421 let snapshot = self.create_snapshot_for_diagnostic();
422 self.bump();
423 match self.parse_use_item() {
424 Ok(u) => {
425 self.dcx().emit_err(diagnostics::RecoverImportAsUse { span, token_name });
426 Ok(Some(u))
427 }
428 Err(e) => {
429 e.cancel();
430 self.restore_snapshot(snapshot);
431 Ok(None)
432 }
433 }
434 }
435
436 fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
437 let tree = self.parse_use_tree()?;
438 if let Err(mut e) = self.expect_semi() {
439 match tree.kind {
440 UseTreeKind::Glob(_) => {
441 e.note("the wildcard token must be last on the path");
442 }
443 UseTreeKind::Nested { .. } => {
444 e.note("glob-like brace syntax must be last on the path");
445 }
446 _ => (),
447 }
448 return Err(e);
449 }
450 Ok(ItemKind::Use(tree))
451 }
452
453 pub(super) fn is_path_start_item(&mut self) -> bool {
455 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{..}) }
461
462 fn is_reuse_item(&mut self) -> Option<ReuseKind> {
463 if !self.token.is_keyword(kw::Reuse) {
464 return None;
465 }
466
467 if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
469 Some(ReuseKind::Path)
470 } else if self.check_impl_frontmatter(1) {
471 Some(ReuseKind::Impl)
472 } else {
473 None
474 }
475 }
476
477 fn isnt_macro_invocation(&mut self) -> bool {
479 self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
480 }
481
482 fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
485 let is_pub = self.prev_token.is_keyword(kw::Pub);
486 let is_const = self.prev_token.is_keyword(kw::Const);
487 let ident_span = self.token.span;
488 let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };
489 let insert_span = ident_span.shrink_to_lo();
490
491 let ident = if self.token.is_ident()
492 && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
493 && self.look_ahead(1, |t| {
494 #[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)
495 }) {
496 self.parse_ident_common(true).unwrap()
497 } else {
498 return Ok(());
499 };
500
501 let mut found_generics = false;
502 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Lt,
token_type: crate::parser::token_type::TokenType::Lt,
}exp!(Lt)) {
503 found_generics = true;
504 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Gt,
token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)]);
505 self.bump(); }
507
508 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)) {
509 if self.look_ahead(1, |t| *t == token::CloseBrace) {
511 Some(diagnostics::MissingKeywordForItemDefinition::EnumOrStruct { span })
513 } else if self.look_ahead(2, |t| *t == token::Colon)
514 || self.look_ahead(3, |t| *t == token::Colon)
515 {
516 Some(diagnostics::MissingKeywordForItemDefinition::Struct {
518 span,
519 insert_span,
520 ident,
521 })
522 } else {
523 Some(diagnostics::MissingKeywordForItemDefinition::Enum {
524 span,
525 insert_span,
526 ident,
527 })
528 }
529 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
530 self.bump(); let is_method = self.recover_self_param();
533
534 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);
535
536 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)) {
537 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)]);
538 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);
540 if is_method {
541 diagnostics::MissingKeywordForItemDefinition::Method {
542 span,
543 insert_span,
544 ident,
545 }
546 } else {
547 diagnostics::MissingKeywordForItemDefinition::Function {
548 span,
549 insert_span,
550 ident,
551 }
552 }
553 } 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)) {
554 diagnostics::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
555 } else {
556 diagnostics::MissingKeywordForItemDefinition::Ambiguous {
557 span,
558 subdiag: if found_generics {
559 None
560 } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
561 Some(diagnostics::AmbiguousMissingKwForItemSub::SuggestMacro {
562 span: ident_span,
563 snippet,
564 })
565 } else {
566 Some(diagnostics::AmbiguousMissingKwForItemSub::HelpMacro)
567 },
568 }
569 };
570 Some(err)
571 } else if found_generics {
572 Some(diagnostics::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
573 } else {
574 None
575 };
576
577 if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
578 }
579
580 fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
581 Ok(None)
583 }
584
585 fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
587 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() {
590 Ok(args) => {
592 self.eat_semi_for_macro_if_needed(&args, Some(&path));
593 self.complain_if_pub_macro(vis, false);
594 Ok(MacCall { path, args })
595 }
596
597 Err(mut err) => {
598 if self.token.is_ident()
600 && let [segment] = path.segments.as_slice()
601 && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
602 {
603 err.span_suggestion_verbose(
604 path.span,
605 "perhaps you meant to define a macro",
606 "macro_rules",
607 Applicability::MachineApplicable,
608 );
609 }
610 Err(err)
611 }
612 }
613 }
614
615 fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
617 let ([start @ end] | [start, .., end]) = attrs else {
618 return Ok(());
619 };
620 let msg = if end.is_doc_comment() {
621 "expected item after doc comment"
622 } else {
623 "expected item after attributes"
624 };
625 let mut err = self.dcx().struct_span_err(end.span, msg);
626 if end.is_doc_comment() {
627 err.span_label(end.span, "this doc comment doesn't document anything");
628 } else {
629 err.span_label(end.span, "expected an item after this");
630 if self.token == TokenKind::Semi {
631 err.span_suggestion_verbose(
632 self.token.span,
633 "remove the semicolon after the attribute",
634 "",
635 Applicability::MaybeIncorrect,
636 );
637 }
638 }
639 if let [.., penultimate, _] = attrs {
640 err.span_label(start.span.to(penultimate.span), "other attributes here");
641 }
642 Err(err)
643 }
644
645 fn is_async_fn(&self) -> bool {
646 self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
647 }
648
649 fn parse_polarity(&mut self) -> ast::ImplPolarity {
650 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) && self.look_ahead(1, |t| t.can_begin_type()) {
652 self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
653 self.bump(); ast::ImplPolarity::Negative(self.prev_token.span)
655 } else {
656 ast::ImplPolarity::Positive
657 }
658 }
659
660 fn parse_item_impl(
675 &mut self,
676 attrs: &mut AttrVec,
677 defaultness: Defaultness,
678 is_reuse: bool,
679 ) -> PResult<'a, ItemKind> {
680 let constness = self.parse_constness(Case::Sensitive);
681 let safety = self.parse_safety(Case::Sensitive);
682 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
683 let mut generics_snapshot = None;
684 let mut generics = if self.choose_generics_over_qpath(0) {
686 self.parse_generics()?
687 } else {
688 if self.look_ahead(0, |t| t == &token::Lt)
691 && self.look_ahead(1, |t| t.is_ident())
692 && self.look_ahead(2, |t| t == &token::Lt)
693 {
694 generics_snapshot = Some(self.create_snapshot_for_diagnostic());
695 }
696
697 let mut generics = Generics::default();
698 generics.span = self.prev_token.span.shrink_to_hi();
701 generics
702 };
703
704 if let Const::Yes(span) = constness {
705 self.psess.gated_spans.gate(sym::const_trait_impl, span);
706 }
707
708 if (self.token_uninterpolated_span().at_least_rust_2018()
710 && self.token.is_keyword(kw::Async))
711 || self.is_kw_followed_by_ident(kw::Async)
712 {
713 self.bump();
714 self.dcx().emit_err(diagnostics::AsyncImpl { span: self.prev_token.span });
715 }
716
717 let polarity = self.parse_polarity();
718
719 let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
721 {
722 let span = self.prev_token.span.between(self.token.span);
723 return Err(self.dcx().create_err(diagnostics::MissingTraitInTraitImpl {
724 span,
725 for_span: span.to(self.token.span),
726 }));
727 } else {
728 self.parse_ty_with_generics_recovery(&generics).map_err(|e| {
729 let Some(mut snapshot) = generics_snapshot else {
730 return e;
731 };
732 snapshot.maybe_type_in_generic_parameter(e)
733 })?
734 };
735 let has_for = self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::For,
token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For));
737 let missing_for_span = self.prev_token.span.between(self.token.span);
738
739 let ty_second = if self.token == token::DotDot {
740 self.bump(); Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
747 } else if has_for || self.token.can_begin_type() {
748 Some(self.parse_ty()?)
749 } else {
750 None
751 };
752
753 generics.where_clause = self.parse_where_clause()?;
754
755 let impl_items = if is_reuse {
756 Default::default()
757 } else {
758 self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
759 };
760
761 let (of_trait, self_ty) = match ty_second {
762 Some(ty_second) => {
763 if !has_for {
765 self.dcx()
766 .emit_err(diagnostics::MissingForInTraitImpl { span: missing_for_span });
767 }
768
769 let ty_first = *ty_first;
770 let path = match ty_first.kind {
771 TyKind::Path(None, path) => path,
773 other => {
774 if let TyKind::ImplTrait(_, bounds) = other
775 && let [bound] = bounds.as_slice()
776 && let GenericBound::Trait(poly_trait_ref) = bound
777 {
778 let extra_impl_kw = ty_first.span.until(bound.span());
782 self.dcx().emit_err(diagnostics::ExtraImplKeywordInTraitImpl {
783 extra_impl_kw,
784 impl_trait_span: ty_first.span,
785 });
786 poly_trait_ref.trait_ref.path.clone()
787 } else {
788 return Err(self.dcx().create_err(
789 diagnostics::ExpectedTraitInTraitImplFoundType {
790 span: ty_first.span,
791 },
792 ));
793 }
794 }
795 };
796 let trait_ref = TraitRef { path, ref_id: ty_first.id };
797
798 let of_trait =
799 Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
800 (of_trait, ty_second)
801 }
802 None => {
803 let self_ty = ty_first;
804 let error = |modifier, modifier_name, modifier_span| {
805 self.dcx().create_err(diagnostics::TraitImplModifierInInherentImpl {
806 span: self_ty.span,
807 modifier,
808 modifier_name,
809 modifier_span,
810 self_ty: self_ty.span,
811 })
812 };
813
814 if let Safety::Unsafe(span) = safety {
815 error("unsafe", "unsafe", span).with_code(E0197).emit();
816 }
817 if let ImplPolarity::Negative(span) = polarity {
818 error("!", "negative", span).emit();
819 }
820 if let Defaultness::Default(def_span) = defaultness {
821 error("default", "default", def_span).emit();
822 }
823 if let Const::Yes(span) = constness {
824 self.psess.gated_spans.gate(sym::const_trait_impl, span);
825 }
826 (None, self_ty)
827 }
828 };
829
830 Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
831 }
832
833 fn parse_item_delegation(
834 &mut self,
835 attrs: &mut AttrVec,
836 defaultness: Defaultness,
837 kind: ReuseKind,
838 ) -> PResult<'a, ItemKind> {
839 let span = self.token.span;
840 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Reuse,
token_type: crate::parser::token_type::TokenType::KwReuse,
}exp!(Reuse))?;
841
842 let item_kind = match kind {
843 ReuseKind::Path => self.parse_path_like_delegation(),
844 ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
845 }?;
846
847 self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
848
849 Ok(item_kind)
850 }
851
852 fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
853 Ok(if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
854 Some(self.parse_block()?)
855 } else {
856 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))?;
857 None
858 })
859 }
860
861 fn parse_impl_delegation(
862 &mut self,
863 span: Span,
864 attrs: &mut AttrVec,
865 defaultness: Defaultness,
866 ) -> PResult<'a, ItemKind> {
867 let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
868 let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
869
870 let until_expr_span = span.to(self.prev_token.span);
871
872 let Some(of_trait) = of_trait else {
873 return Err(self
874 .dcx()
875 .create_err(diagnostics::ImplReuseInherentImpl { span: until_expr_span }));
876 };
877
878 let body = self.parse_delegation_body()?;
879 let whole_reuse_span = span.to(self.prev_token.span);
880
881 items.push(Box::new(AssocItem {
882 id: DUMMY_NODE_ID,
883 attrs: Default::default(),
884 span: whole_reuse_span,
885 tokens: None,
886 vis: Visibility { kind: VisibilityKind::Inherited, span: whole_reuse_span },
887 kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
888 qself: None,
889 prefix: of_trait.trait_ref.path.clone(),
890 suffixes: DelegationSuffixes::Glob(whole_reuse_span),
891 body,
892 })),
893 }));
894
895 Ok(impl_item)
896 }
897
898 fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
899 let (qself, path) = if self.eat_lt() {
900 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
901 (Some(qself), path)
902 } else {
903 (None, self.parse_path(PathStyle::Expr)?)
904 };
905
906 let rename = |this: &mut Self| {
907 Ok(if this.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::As,
token_type: crate::parser::token_type::TokenType::KwAs,
}exp!(As)) { Some(this.parse_ident()?) } else { None })
908 };
909
910 Ok(if self.eat_path_sep() {
911 let suffixes = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
912 DelegationSuffixes::Glob(self.prev_token.span)
913 } else {
914 let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
915 DelegationSuffixes::List(
916 self.parse_delim_comma_seq(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), parse_suffix)?.0,
917 )
918 };
919
920 ItemKind::DelegationMac(Box::new(DelegationMac {
921 qself,
922 prefix: path,
923 suffixes,
924 body: self.parse_delegation_body()?,
925 }))
926 } else {
927 let rename = rename(self)?;
928 let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
929
930 ItemKind::Delegation(Box::new(Delegation {
931 id: DUMMY_NODE_ID,
932 qself,
933 path,
934 ident,
935 rename,
936 body: self.parse_delegation_body()?,
937 source: DelegationSource::Single,
938 }))
939 })
940 }
941
942 fn parse_item_list<T>(
943 &mut self,
944 attrs: &mut AttrVec,
945 mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
946 ) -> PResult<'a, ThinVec<T>> {
947 let open_brace_span = self.token.span;
948
949 if self.token == TokenKind::Semi {
951 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
952 self.bump();
953 return Ok(ThinVec::new());
954 }
955
956 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
957 attrs.extend(self.parse_inner_attributes()?);
958
959 let mut items = ThinVec::new();
960 while !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)) {
961 if self.recover_doc_comment_before_brace() {
962 continue;
963 }
964 self.recover_vcs_conflict_marker();
965 match parse_item(self) {
966 Ok(None) => {
967 let mut is_unnecessary_semicolon = (self.token == token::Semi
968 && self.prev_token == token::Semi)
969 || !items.is_empty()
970 && self
988 .span_to_snippet(self.prev_token.span)
989 .is_ok_and(|snippet| snippet == "}")
990 && self.token == token::Semi;
991 let mut semicolon_span = self.token.span;
992 if !is_unnecessary_semicolon {
993 is_unnecessary_semicolon =
995 self.token == token::OpenBrace && self.prev_token == token::Semi;
996 semicolon_span = self.prev_token.span;
997 }
998 let non_item_span = self.token.span;
1000 let is_let = self.token.is_keyword(kw::Let);
1001
1002 let mut err =
1003 self.dcx().struct_span_err(non_item_span, "non-item in item list");
1004 self.consume_block(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), ConsumeClosingDelim::Yes);
1005 if is_let {
1006 err.span_suggestion_verbose(
1007 non_item_span,
1008 "consider using `const` instead of `let` for associated const",
1009 "const",
1010 Applicability::MachineApplicable,
1011 );
1012 } else {
1013 err.span_label(open_brace_span, "item list starts here")
1014 .span_label(non_item_span, "non-item starts here")
1015 .span_label(self.prev_token.span, "item list ends here");
1016 }
1017 if is_unnecessary_semicolon {
1018 err.span_suggestion_verbose(
1019 semicolon_span,
1020 "consider removing this semicolon",
1021 "",
1022 Applicability::MaybeIncorrect,
1023 );
1024 }
1025 err.emit();
1026 break;
1027 }
1028 Ok(Some(item)) => items.extend(item),
1029 Err(err) => {
1030 self.consume_block(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), ConsumeClosingDelim::Yes);
1031 err.with_span_label(
1032 open_brace_span,
1033 "while parsing this item list starting here",
1034 )
1035 .with_span_label(self.prev_token.span, "the item list ends here")
1036 .emit();
1037 break;
1038 }
1039 }
1040 }
1041 Ok(items)
1042 }
1043
1044 fn recover_doc_comment_before_brace(&mut self) -> bool {
1046 if let token::DocComment(..) = self.token.kind {
1047 if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
1048 {
self.dcx().struct_span_err(self.token.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("found a documentation comment that doesn\'t document anything"))
})).with_code(E0584)
}struct_span_code_err!(
1050 self.dcx(),
1051 self.token.span,
1052 E0584,
1053 "found a documentation comment that doesn't document anything",
1054 )
1055 .with_span_label(self.token.span, "this doc comment doesn't document anything")
1056 .with_help(
1057 "doc comments must come before what they document, if a comment was \
1058 intended use `//`",
1059 )
1060 .emit();
1061 self.bump();
1062 return true;
1063 }
1064 }
1065 false
1066 }
1067
1068 fn parse_defaultness(&mut self) -> Defaultness {
1070 if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Default,
token_type: crate::parser::token_type::TokenType::KwDefault,
}exp!(Default))
1074 && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
1075 {
1076 self.psess.gated_spans.gate(sym::specialization, self.token.span);
1077 self.bump(); Defaultness::Default(self.prev_token_uninterpolated_span())
1079 } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Final,
token_type: crate::parser::token_type::TokenType::KwFinal,
}exp!(Final)) {
1080 self.psess.gated_spans.gate(sym::final_associated_functions, self.prev_token.span);
1081 Defaultness::Final(self.prev_token_uninterpolated_span())
1082 } else {
1083 Defaultness::Implicit
1084 }
1085 }
1086
1087 fn check_trait_front_matter(&mut self) -> bool {
1089 const SUFFIXES: &[&[Symbol]] = &[
1090 &[kw::Trait],
1091 &[kw::Auto, kw::Trait],
1092 &[kw::Unsafe, kw::Trait],
1093 &[kw::Unsafe, kw::Auto, kw::Trait],
1094 &[kw::Const, kw::Trait],
1095 &[kw::Const, kw::Auto, kw::Trait],
1096 &[kw::Const, kw::Unsafe, kw::Trait],
1097 &[kw::Const, kw::Unsafe, kw::Auto, kw::Trait],
1098 ];
1099 if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl)) && self.look_ahead(1, |t| t == &token::OpenParen) {
1101 if self.is_keyword_ahead(2, &[kw::In]) {
1103 return true;
1104 }
1105 if self.is_keyword_ahead(2, &[kw::Crate, kw::SelfLower, kw::Super])
1107 && self.look_ahead(3, |t| t == &token::CloseParen)
1108 && SUFFIXES.iter().any(|suffix| {
1109 suffix.iter().enumerate().all(|(i, kw)| self.is_keyword_ahead(i + 4, &[*kw]))
1110 })
1111 {
1112 return true;
1113 }
1114 SUFFIXES.iter().any(|suffix| {
1116 suffix.iter().enumerate().all(|(i, kw)| {
1117 self.tree_look_ahead(i + 2, |t| {
1118 if let TokenTree::Token(token, _) = t {
1119 token.is_keyword(*kw)
1120 } else {
1121 false
1122 }
1123 })
1124 .unwrap_or(false)
1125 })
1126 })
1127 } else {
1128 SUFFIXES.iter().any(|suffix| {
1129 suffix.iter().enumerate().all(|(i, kw)| {
1130 if i == 0 {
1132 match *kw {
1133 kw::Const => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)),
1134 kw::Unsafe => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe)),
1135 kw::Auto => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Auto,
token_type: crate::parser::token_type::TokenType::KwAuto,
}exp!(Auto)),
1136 kw::Trait => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait)),
1137 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1138 }
1139 } else {
1140 self.is_keyword_ahead(i, &[*kw])
1141 }
1142 })
1143 })
1144 }
1145 }
1146
1147 fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
1149 let impl_restriction = self.parse_impl_restriction()?;
1150 let constness = self.parse_constness(Case::Sensitive);
1151 if let Const::Yes(span) = constness {
1152 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1153 }
1154 let safety = self.parse_safety(Case::Sensitive);
1155 let is_auto = if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Auto,
token_type: crate::parser::token_type::TokenType::KwAuto,
}exp!(Auto)) {
1157 self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
1158 IsAuto::Yes
1159 } else {
1160 IsAuto::No
1161 };
1162
1163 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait))?;
1164 let ident = self.parse_ident()?;
1165 let mut generics = self.parse_generics()?;
1166
1167 let had_colon = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon));
1169 let span_at_colon = self.prev_token.span;
1170 let bounds = if had_colon { self.parse_generic_bounds()? } else { ThinVec::new() };
1171
1172 let span_before_eq = self.prev_token.span;
1173 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1174 if had_colon {
1176 let span = span_at_colon.to(span_before_eq);
1177 self.dcx().emit_err(diagnostics::BoundsNotAllowedOnTraitAliases { span });
1178 }
1179
1180 let bounds = self.parse_generic_bounds()?;
1181 generics.where_clause = self.parse_where_clause()?;
1182 self.expect_semi()?;
1183
1184 let whole_span = lo.to(self.prev_token.span);
1185 if is_auto == IsAuto::Yes {
1186 self.dcx().emit_err(diagnostics::TraitAliasCannotBeAuto { span: whole_span });
1187 }
1188 if let Safety::Unsafe(_) = safety {
1189 self.dcx().emit_err(diagnostics::TraitAliasCannotBeUnsafe { span: whole_span });
1190 }
1191 if let RestrictionKind::Restricted { .. } = impl_restriction.kind {
1192 self.dcx()
1193 .emit_err(diagnostics::TraitAliasCannotBeImplRestricted { span: whole_span });
1194 }
1195
1196 self.psess.gated_spans.gate(sym::trait_alias, whole_span);
1197
1198 Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
1199 } else {
1200 generics.where_clause = self.parse_where_clause()?;
1202 let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
1203 Ok(ItemKind::Trait(Box::new(Trait {
1204 impl_restriction,
1205 constness,
1206 is_auto,
1207 safety,
1208 ident,
1209 generics,
1210 bounds,
1211 items,
1212 })))
1213 }
1214 }
1215
1216 pub fn parse_impl_item(
1217 &mut self,
1218 force_collect: ForceCollect,
1219 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1220 let fn_parse_mode =
1221 FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
1222 self.parse_assoc_item(fn_parse_mode, force_collect)
1223 }
1224
1225 pub fn parse_trait_item(
1226 &mut self,
1227 force_collect: ForceCollect,
1228 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1229 let fn_parse_mode = FnParseMode {
1230 req_name: |edition, _| edition >= Edition::Edition2018,
1231 context: FnContext::Trait,
1232 req_body: false,
1233 };
1234 self.parse_assoc_item(fn_parse_mode, force_collect)
1235 }
1236
1237 fn parse_assoc_item(
1239 &mut self,
1240 fn_parse_mode: FnParseMode,
1241 force_collect: ForceCollect,
1242 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1243 Ok(self
1244 .parse_item_(
1245 fn_parse_mode,
1246 force_collect,
1247 AllowConstBlockItems::DoesNotMatter, )?
1249 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1250 let kind = match AssocItemKind::try_from(kind) {
1251 Ok(kind) => kind,
1252 Err(kind) => match kind {
1253 ItemKind::Static(StaticItem {
1254 ident,
1255 ty,
1256 safety: _,
1257 mutability: _,
1258 expr,
1259 define_opaque,
1260 eii_impl: _,
1261 }) => {
1262 self.dcx()
1263 .emit_err(diagnostics::AssociatedStaticItemNotAllowed { span });
1264 AssocItemKind::Const(Box::new(ConstItem {
1265 defaultness: Defaultness::Implicit,
1266 ident,
1267 generics: Generics::default(),
1268 ty,
1269 body: expr,
1270 kind: ConstItemKind::Body,
1271 define_opaque,
1272 }))
1273 }
1274 _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
1275 },
1276 };
1277 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1278 }))
1279 }
1280
1281 fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
1287 let ident = self.parse_ident()?;
1288 let mut generics = self.parse_generics()?;
1289
1290 let bounds =
1292 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) { self.parse_generic_bounds()? } else { ThinVec::new() };
1293 generics.where_clause = self.parse_where_clause()?;
1294
1295 let ty = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) { Some(self.parse_ty()?) } else { None };
1296
1297 let after_where_clause = self.parse_where_clause()?;
1298
1299 self.expect_semi()?;
1300
1301 Ok(ItemKind::TyAlias(Box::new(TyAlias {
1302 defaultness,
1303 ident,
1304 generics,
1305 after_where_clause,
1306 bounds,
1307 ty,
1308 })))
1309 }
1310
1311 fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
1321 let lo = self.token.span;
1322
1323 let mut prefix = ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo() };
1324 let kind =
1325 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) || self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) || self.is_import_coupler() {
1326 let mod_sep_ctxt = self.token.span.ctxt();
1328 if self.eat_path_sep() {
1329 prefix
1330 .segments
1331 .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
1332 }
1333
1334 self.parse_use_tree_glob_or_nested()?
1335 } else {
1336 prefix = self.parse_path(PathStyle::Mod)?;
1338
1339 if self.eat_path_sep() {
1340 self.parse_use_tree_glob_or_nested()?
1341 } else {
1342 while self.eat_noexpect(&token::Colon) {
1344 self.dcx().emit_err(diagnostics::SingleColonImportPath {
1345 span: self.prev_token.span,
1346 });
1347
1348 self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
1350 prefix.span = lo.to(self.prev_token.span);
1351 }
1352
1353 UseTreeKind::Simple(self.parse_rename()?)
1354 }
1355 };
1356
1357 Ok(UseTree { prefix, kind })
1358 }
1359
1360 fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
1362 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
1363 UseTreeKind::Glob(self.prev_token.span)
1364 } else {
1365 let lo = self.token.span;
1366 UseTreeKind::Nested {
1367 items: self.parse_use_tree_list()?,
1368 span: lo.to(self.prev_token.span),
1369 }
1370 })
1371 }
1372
1373 fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
1379 self.parse_delim_comma_seq(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), |p| {
1380 p.recover_vcs_conflict_marker();
1381 Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
1382 })
1383 .map(|(r, _)| r)
1384 }
1385
1386 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1387 if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::As,
token_type: crate::parser::token_type::TokenType::KwAs,
}exp!(As)) {
1388 self.parse_ident_or_underscore().map(Some)
1389 } else {
1390 Ok(None)
1391 }
1392 }
1393
1394 fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
1395 match self.token.ident() {
1396 Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
1397 self.bump();
1398 Ok(ident)
1399 }
1400 _ => self.parse_ident(),
1401 }
1402 }
1403
1404 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1413 let orig_ident = self.parse_crate_name_with_dashes()?;
1415 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1416 (Some(orig_ident.name), rename)
1417 } else {
1418 (None, orig_ident)
1419 };
1420 self.expect_semi()?;
1421 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1422 }
1423
1424 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1425 let ident = if self.token.is_keyword(kw::SelfLower) {
1426 self.parse_path_segment_ident()
1427 } else {
1428 self.parse_ident()
1429 }?;
1430
1431 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1432 if self.token != dash.tok {
1433 return Ok(ident);
1434 }
1435
1436 let mut dashes = ::alloc::vec::Vec::new()vec![];
1438 let mut idents = ::alloc::vec::Vec::new()vec![];
1439 while self.eat(dash) {
1440 dashes.push(self.prev_token.span);
1441 idents.push(self.parse_ident()?);
1442 }
1443
1444 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1445 let mut fixed_name = ident.name.to_string();
1446 for part in idents {
1447 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1448 }
1449
1450 self.dcx().emit_err(diagnostics::ExternCrateNameWithDashes {
1451 span: fixed_name_sp,
1452 sugg: diagnostics::ExternCrateNameWithDashesSugg { dashes },
1453 });
1454
1455 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1456 }
1457
1458 fn parse_item_foreign_mod(
1469 &mut self,
1470 attrs: &mut AttrVec,
1471 mut safety: Safety,
1472 ) -> PResult<'a, ItemKind> {
1473 let extern_span = self.prev_token_uninterpolated_span();
1474 let abi = self.parse_abi(); if safety == Safety::Default
1477 && self.token.is_keyword(kw::Unsafe)
1478 && self.look_ahead(1, |t| *t == token::OpenBrace)
1479 {
1480 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)).unwrap_err().emit();
1481 safety = Safety::Unsafe(self.token.span);
1482 let _ = self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe));
1483 }
1484 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1485 extern_span,
1486 safety,
1487 abi,
1488 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1489 }))
1490 }
1491
1492 pub fn parse_foreign_item(
1494 &mut self,
1495 force_collect: ForceCollect,
1496 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1497 let fn_parse_mode = FnParseMode {
1498 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1499 context: FnContext::Free,
1500 req_body: false,
1501 };
1502 Ok(self
1503 .parse_item_(
1504 fn_parse_mode,
1505 force_collect,
1506 AllowConstBlockItems::DoesNotMatter, )?
1508 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1509 let kind = match ForeignItemKind::try_from(kind) {
1510 Ok(kind) => kind,
1511 Err(kind) => match kind {
1512 ItemKind::Const(ConstItem { ident, ty, body, .. }) => {
1513 let const_span = Some(span.with_hi(ident.span.lo()))
1514 .filter(|span| span.can_be_used_for_suggestions());
1515 self.dcx().emit_err(diagnostics::ExternItemCannotBeConst {
1516 ident_span: ident.span,
1517 const_span,
1518 });
1519 ForeignItemKind::Static(Box::new(StaticItem {
1520 ident,
1521 ty,
1522 mutability: Mutability::Not,
1523 expr: body,
1524 safety: Safety::Default,
1525 define_opaque: None,
1526 eii_impl: None,
1527 }))
1528 }
1529 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1530 },
1531 };
1532 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1533 }))
1534 }
1535
1536 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1537 let span = self.psess.source_map().guess_head_span(span);
1539 let descr = kind.descr();
1540 let help = match kind {
1541 ItemKind::DelegationMac(DelegationMac {
1542 suffixes: DelegationSuffixes::Glob(_),
1543 ..
1544 }) => false,
1545 _ => true,
1546 };
1547 self.dcx().emit_err(diagnostics::BadItemKind { span, descr, ctx, help });
1548 None
1549 }
1550
1551 fn is_use_closure(&self) -> bool {
1552 if self.token.is_keyword(kw::Use) {
1553 self.look_ahead(1, |token| {
1555 let dist =
1557 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1558
1559 self.look_ahead(dist, |token| #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr))
1560 })
1561 } else {
1562 false
1563 }
1564 }
1565
1566 pub(super) fn is_unsafe_foreign_mod(&self) -> bool {
1567 if !self.token.is_keyword(kw::Unsafe) {
1569 return false;
1570 }
1571 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1573 return false;
1574 }
1575
1576 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1578
1579 self.tree_look_ahead(n, |t| #[allow(non_exhaustive_omitted_patterns)] match t {
TokenTree::Delimited(_, _, Delimiter::Brace, _) => true,
_ => false,
}matches!(t, TokenTree::Delimited(_, _, Delimiter::Brace, _)))
1584 == Some(true)
1585 }
1586
1587 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1588 let is_global_static = if self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Static,
token_type: crate::parser::token_type::TokenType::KwStatic,
}exp!(Static), case) {
1589 !self.look_ahead(1, |token| {
1591 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1592 return true;
1593 }
1594 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1595 })
1596 } else {
1597 (self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe), case)
1599 || self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe), case))
1600 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1601 };
1602
1603 if is_global_static {
1604 let safety = self.parse_safety(case);
1605 let _ = self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Static,
token_type: crate::parser::token_type::TokenType::KwStatic,
}exp!(Static), case);
1606 Some(safety)
1607 } else {
1608 None
1609 }
1610 }
1611
1612 fn recover_const_mut(&mut self, const_span: Span) {
1614 if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mut,
token_type: crate::parser::token_type::TokenType::KwMut,
}exp!(Mut)) {
1615 let span = self.prev_token.span;
1616 self.dcx()
1617 .emit_err(diagnostics::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1618 } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Let,
token_type: crate::parser::token_type::TokenType::KwLet,
}exp!(Let)) {
1619 let span = self.prev_token.span;
1620 self.dcx()
1621 .emit_err(diagnostics::ConstLetMutuallyExclusive { span: const_span.to(span) });
1622 }
1623 }
1624
1625 fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
1626 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1627 let const_span = self.prev_token.span;
1628 self.psess.gated_spans.gate(sym::const_block_items, const_span);
1629 let block = self.parse_block()?;
1630 Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
1631 }
1632
1633 fn parse_static_item(
1640 &mut self,
1641 safety: Safety,
1642 mutability: Mutability,
1643 ) -> PResult<'a, ItemKind> {
1644 let ident = self.parse_ident()?;
1645
1646 if self.token == TokenKind::Lt && self.may_recover() {
1647 let generics = self.parse_generics()?;
1648 self.dcx().emit_err(diagnostics::StaticWithGenerics { span: generics.span });
1649 }
1650
1651 let ty = match (self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)), self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) | self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))) {
1654 (true, false) => self.parse_ty()?,
1655 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1658 };
1659
1660 let expr = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) { Some(self.parse_expr()?) } else { None };
1661
1662 self.expect_semi()?;
1663
1664 let item =
1665 StaticItem { ident, ty, safety, mutability, expr, define_opaque: None, eii_impl: None };
1666 Ok(ItemKind::Static(Box::new(item)))
1667 }
1668
1669 fn parse_const_item(
1678 &mut self,
1679 const_span: Span,
1680 ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<Box<Expr>>)> {
1681 let ident = self.parse_ident_or_underscore()?;
1682
1683 let mut generics = self.parse_generics()?;
1684
1685 if !generics.span.is_empty() {
1688 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1689 }
1690
1691 let ty = match (
1694 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1695 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)),
1696 ) {
1697 (true, false) => self.parse_ty()?,
1698 (colon, _) => self.recover_missing_global_item_type(colon, None),
1700 };
1701
1702 let before_where_clause =
1705 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1706
1707 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 };
1708
1709 let after_where_clause = self.parse_where_clause()?;
1710
1711 if before_where_clause.has_where_token
1715 && let Some(rhs) = &rhs
1716 {
1717 self.dcx().emit_err(diagnostics::WhereClauseBeforeConstBody {
1718 span: before_where_clause.span,
1719 name: ident.span,
1720 body: rhs.span,
1721 sugg: if !after_where_clause.has_where_token {
1722 self.psess.source_map().span_to_snippet(rhs.span).ok().map(|body_s| {
1723 diagnostics::WhereClauseBeforeConstBodySugg {
1724 left: before_where_clause.span.shrink_to_lo(),
1725 snippet: body_s,
1726 right: before_where_clause.span.shrink_to_hi().to(rhs.span),
1727 }
1728 })
1729 } else {
1730 None
1733 },
1734 });
1735 }
1736
1737 let mut predicates = before_where_clause.predicates;
1744 predicates.extend(after_where_clause.predicates);
1745 let where_clause = WhereClause {
1746 has_where_token: before_where_clause.has_where_token
1747 || after_where_clause.has_where_token,
1748 predicates,
1749 span: if after_where_clause.has_where_token {
1750 after_where_clause.span
1751 } else {
1752 before_where_clause.span
1753 },
1754 };
1755
1756 if where_clause.has_where_token {
1757 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1758 }
1759
1760 generics.where_clause = where_clause;
1761
1762 if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
1763 return Ok((ident, generics, ty, Some(rhs)));
1764 }
1765 self.expect_semi()?;
1766
1767 Ok((ident, generics, ty, rhs))
1768 }
1769
1770 fn recover_missing_global_item_type(
1773 &mut self,
1774 colon_present: bool,
1775 m: Option<Mutability>,
1776 ) -> Box<Ty> {
1777 let kind = match m {
1780 Some(Mutability::Mut) => "static mut",
1781 Some(Mutability::Not) => "static",
1782 None => "const",
1783 };
1784
1785 let colon = match colon_present {
1786 true => "",
1787 false => ":",
1788 };
1789
1790 let span = self.prev_token.span.shrink_to_hi();
1791 let err = self.dcx().create_err(diagnostics::MissingConstType { span, colon, kind });
1792 err.stash(span, StashKey::ItemNoType);
1793
1794 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID })
1797 }
1798
1799 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1801 if self.token.is_keyword(kw::Struct) {
1802 let span = self.prev_token.span.to(self.token.span);
1803 let err = diagnostics::EnumStructMutuallyExclusive { span };
1804 if self.look_ahead(1, |t| t.is_ident()) {
1805 self.bump();
1806 self.dcx().emit_err(err);
1807 } else {
1808 return Err(self.dcx().create_err(err));
1809 }
1810 }
1811
1812 let prev_span = self.prev_token.span;
1813 let ident = self.parse_ident()?;
1814 let mut generics = self.parse_generics()?;
1815 generics.where_clause = self.parse_where_clause()?;
1816
1817 let (variants, _) = if self.token == TokenKind::Semi {
1819 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
1820 self.bump();
1821 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1822 } else {
1823 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| {
1824 p.parse_enum_variant(ident.span)
1825 })
1826 .map_err(|mut err| {
1827 err.span_label(ident.span, "while parsing this enum");
1828 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1830 let snapshot = self.create_snapshot_for_diagnostic();
1831 self.bump();
1832 match self.parse_ty() {
1833 Ok(_) => {
1834 err.span_suggestion_verbose(
1835 prev_span,
1836 "perhaps you meant to use `struct` here",
1837 "struct",
1838 Applicability::MaybeIncorrect,
1839 );
1840 }
1841 Err(e) => {
1842 e.cancel();
1843 }
1844 }
1845 self.restore_snapshot(snapshot);
1846 }
1847 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1848 self.bump(); err
1850 })?
1851 };
1852
1853 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1854 Ok(ItemKind::Enum(ident, generics, enum_definition))
1855 }
1856
1857 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1858 self.recover_vcs_conflict_marker();
1859 let variant_attrs = self.parse_outer_attributes()?;
1860 self.recover_vcs_conflict_marker();
1861 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1862 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1863 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1864 let vlo = this.token.span;
1865
1866 let vis = this.parse_visibility(FollowedByType::No)?;
1867 if !this.recover_nested_adt_item(kw::Enum)? {
1868 return Ok((None, Trailing::No, UsePreAttrPos::No));
1869 }
1870 let ident = this.parse_field_ident("enum", vlo)?;
1871
1872 if this.token == token::Bang {
1873 if let Err(err) = this.unexpected() {
1874 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();
1875 }
1876
1877 this.bump();
1878 this.parse_delim_args()?;
1879
1880 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1881 }
1882
1883 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)) {
1884 let (fields, recovered) =
1886 match this.parse_record_struct_body("struct", ident.span, false) {
1887 Ok((fields, recovered)) => (fields, recovered),
1888 Err(mut err) => {
1889 if this.token == token::Colon {
1890 return Err(err);
1892 }
1893 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1894 this.bump(); err.span_label(span, "while parsing this enum");
1896 err.help(help);
1897 let guar = err.emit();
1898 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1899 }
1900 };
1901 VariantData::Struct { fields, recovered }
1902 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1903 let body = match this.parse_tuple_struct_body() {
1904 Ok(body) => body,
1905 Err(mut err) => {
1906 if this.token == token::Colon {
1907 return Err(err);
1909 }
1910 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
1911 this.bump(); err.span_label(span, "while parsing this enum");
1913 err.help(help);
1914 err.emit();
1915 ::thin_vec::ThinVec::new()thin_vec![]
1916 }
1917 };
1918 VariantData::Tuple(body, DUMMY_NODE_ID)
1919 } else {
1920 VariantData::Unit(DUMMY_NODE_ID)
1921 };
1922
1923 let disr_expr =
1924 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 };
1925
1926 let span = vlo.to(this.prev_token.span);
1927 if ident.name == kw::Underscore {
1928 this.psess.gated_spans.gate(sym::unnamed_enum_variants, span);
1929 }
1930 let vr = ast::Variant {
1931 ident,
1932 vis,
1933 id: DUMMY_NODE_ID,
1934 attrs: variant_attrs,
1935 data: struct_def,
1936 disr_expr,
1937 span,
1938 is_placeholder: false,
1939 };
1940
1941 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
1942 })
1943 .map_err(|mut err| {
1944 err.help(help);
1945 err
1946 })
1947 }
1948
1949 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
1951 let ident = self.parse_ident()?;
1952
1953 let mut generics = self.parse_generics()?;
1954
1955 let vdata = if self.token.is_keyword(kw::Where) {
1970 let tuple_struct_body;
1971 (generics.where_clause, tuple_struct_body) =
1972 self.parse_struct_where_clause(ident, generics.span)?;
1973
1974 if let Some(body) = tuple_struct_body {
1975 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
1977 self.expect_semi()?;
1978 body
1979 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1980 VariantData::Unit(DUMMY_NODE_ID)
1982 } else {
1983 let (fields, recovered) = self.parse_record_struct_body(
1985 "struct",
1986 ident.span,
1987 generics.where_clause.has_where_token,
1988 )?;
1989 VariantData::Struct { fields, recovered }
1990 }
1991 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1993 VariantData::Unit(DUMMY_NODE_ID)
1994 } else if self.token == token::OpenBrace {
1996 let (fields, recovered) = self.parse_record_struct_body(
1997 "struct",
1998 ident.span,
1999 generics.where_clause.has_where_token,
2000 )?;
2001 VariantData::Struct { fields, recovered }
2002 } else if self.token == token::OpenParen {
2004 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
2005 generics.where_clause = self.parse_where_clause()?;
2006 self.expect_semi()?;
2007 body
2008 } else {
2009 let err = diagnostics::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
2010 return Err(self.dcx().create_err(err));
2011 };
2012
2013 Ok(ItemKind::Struct(ident, generics, vdata))
2014 }
2015
2016 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
2018 let ident = self.parse_ident()?;
2019
2020 let mut generics = self.parse_generics()?;
2021
2022 let vdata = if self.token.is_keyword(kw::Where) {
2023 generics.where_clause = self.parse_where_clause()?;
2024 let (fields, recovered) = self.parse_record_struct_body(
2025 "union",
2026 ident.span,
2027 generics.where_clause.has_where_token,
2028 )?;
2029 VariantData::Struct { fields, recovered }
2030 } else if self.token == token::OpenBrace {
2031 let (fields, recovered) = self.parse_record_struct_body(
2032 "union",
2033 ident.span,
2034 generics.where_clause.has_where_token,
2035 )?;
2036 VariantData::Struct { fields, recovered }
2037 } else {
2038 let token_str = super::token_descr(&self.token);
2039 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}");
2040 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2041 err.span_label(self.token.span, "expected `where` or `{` after union name");
2042 return Err(err);
2043 };
2044
2045 Ok(ItemKind::Union(ident, generics, vdata))
2046 }
2047
2048 pub(crate) fn parse_record_struct_body(
2053 &mut self,
2054 adt_ty: &str,
2055 ident_span: Span,
2056 parsed_where: bool,
2057 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
2058 let mut fields = ThinVec::new();
2059 let mut recovered = Recovered::No;
2060 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2061 while self.token != token::CloseBrace {
2062 match self.parse_field_def(adt_ty, ident_span) {
2063 Ok(field) => {
2064 fields.push(field);
2065 }
2066 Err(mut err) => {
2067 self.consume_block(
2068 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
2069 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
2070 ConsumeClosingDelim::No,
2071 );
2072 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}"));
2073 let guar = err.emit();
2074 recovered = Recovered::Yes(guar);
2075 break;
2076 }
2077 }
2078 }
2079 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
2080 } else {
2081 let token_str = super::token_descr(&self.token);
2082 let where_str = if parsed_where { "" } else { "`where`, or " };
2083 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}");
2084 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2085 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",));
2086 return Err(err);
2087 }
2088
2089 Ok((fields, recovered))
2090 }
2091
2092 fn parse_unsafe_field(&mut self) -> Safety {
2093 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)) {
2095 let span = self.prev_token.span;
2096 self.psess.gated_spans.gate(sym::unsafe_fields, span);
2097 Safety::Unsafe(span)
2098 } else {
2099 Safety::Default
2100 }
2101 }
2102 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
2105 let openparen_span = self.token.span;
2106 let mut encountered_colon = false;
2107 self.parse_paren_comma_seq(|p| {
2108 let attrs = p.parse_outer_attributes()?;
2109 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
2110 let mut snapshot = None;
2111 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
2112 snapshot = Some(p.create_snapshot_for_diagnostic());
2116 }
2117 let lo = p.token.span;
2118 let vis = match p.parse_visibility(FollowedByType::Yes) {
2119 Ok(vis) => vis,
2120 Err(err) => {
2121 if let Some(ref mut snapshot) = snapshot {
2122 snapshot.recover_vcs_conflict_marker();
2123 }
2124 return Err(err);
2125 }
2126 };
2127 let mut_restriction = p.parse_mut_restriction()?;
2128 encountered_colon |=
2129 p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
2130 let ty = match p.parse_ty() {
2133 Ok(ty) => ty,
2134 Err(err) => {
2135 if let Some(ref mut snapshot) = snapshot {
2136 snapshot.recover_vcs_conflict_marker();
2137 }
2138 return Err(err);
2139 }
2140 };
2141 let mut default = None;
2142 if p.token == token::Eq {
2143 let mut snapshot = p.create_snapshot_for_diagnostic();
2144 snapshot.bump();
2145 match snapshot.parse_expr_anon_const() {
2146 Ok(const_expr) => {
2147 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2148 p.psess.gated_spans.gate(sym::default_field_values, sp);
2149 p.restore_snapshot(snapshot);
2150 default = Some(const_expr);
2151 }
2152 Err(err) => {
2153 err.cancel();
2154 }
2155 }
2156 }
2157
2158 Ok((
2159 FieldDef {
2160 span: lo.to(ty.span),
2161 vis,
2162 extras: Self::field_def_extras(Safety::Default, mut_restriction, default),
2163 ident: None,
2164 id: DUMMY_NODE_ID,
2165 ty,
2166 attrs,
2167 is_placeholder: false,
2168 },
2169 Trailing::from(p.token == token::Comma),
2170 UsePreAttrPos::No,
2171 ))
2172 })
2173 })
2174 .map(|(r, _)| r)
2175 .map_err(|mut error| {
2176 if self.token == token::Colon {
2177 error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
2178 }
2179 if encountered_colon {
2180 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
2181 self.bump();
2182 error.subdiagnostic(UseRegularStructSuggestion {
2183 open: openparen_span,
2184 close: self.prev_token.span,
2185 semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
2186 });
2187 }
2188 error
2189 })
2190 }
2191
2192 fn field_def_extras(
2193 safety: Safety,
2194 mut_restriction: MutRestriction,
2195 default: Option<AnonConst>,
2196 ) -> Option<Box<FieldDefExtras>> {
2197 match (safety, mut_restriction, default) {
2198 (
2199 Safety::Default,
2200 MutRestriction { kind: RestrictionKind::Unrestricted, span: _ },
2203 None,
2204 ) => None,
2205 (safety, mut_restriction, default) => {
2206 Some(Box::new(FieldDefExtras { safety, mut_restriction, default }))
2207 }
2208 }
2209 }
2210
2211 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2213 self.recover_vcs_conflict_marker();
2214 let attrs = self.parse_outer_attributes()?;
2215 self.recover_vcs_conflict_marker();
2216 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2217 let lo = this.token.span;
2218 let vis = this.parse_visibility(FollowedByType::No)?;
2219 let mut_restriction = this.parse_mut_restriction()?;
2220 let safety = this.parse_unsafe_field();
2221 this.parse_single_struct_field(
2222 adt_ty,
2223 lo,
2224 vis,
2225 mut_restriction,
2226 safety,
2227 attrs,
2228 ident_span,
2229 )
2230 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2231 })
2232 }
2233
2234 fn parse_single_struct_field(
2236 &mut self,
2237 adt_ty: &str,
2238 lo: Span,
2239 vis: Visibility,
2240 mut_restriction: MutRestriction,
2241 safety: Safety,
2242 attrs: AttrVec,
2243 ident_span: Span,
2244 ) -> PResult<'a, FieldDef> {
2245 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, mut_restriction, safety, attrs)?;
2246 match self.token.kind {
2247 token::Comma => {
2248 self.bump();
2249 }
2250 token::Semi => {
2251 self.bump();
2252 let sp = self.prev_token.span;
2253 let mut err =
2254 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 `,`"));
2255 err.span_suggestion_short(
2256 sp,
2257 "replace `;` with `,`",
2258 ",",
2259 Applicability::MachineApplicable,
2260 );
2261 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}"));
2262 err.emit();
2263 }
2264 token::CloseBrace => {}
2265 token::DocComment(..) => {
2266 let previous_span = self.prev_token.span;
2267 let mut err = diagnostics::DocCommentDoesNotDocumentAnything {
2268 span: self.token.span,
2269 missing_comma: None,
2270 };
2271 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 {
2273 self.dcx().emit_err(err);
2274 } else {
2275 let sp = previous_span.shrink_to_hi();
2276 err.missing_comma = Some(sp);
2277 return Err(self.dcx().create_err(err));
2278 }
2279 }
2280 _ => {
2281 let sp = self.prev_token.span.shrink_to_hi();
2282 let msg =
2283 ::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));
2284
2285 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2287 && let Some(last_segment) = segments.last()
2288 {
2289 let guar = self.check_trailing_angle_brackets(
2290 last_segment,
2291 &[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)],
2292 );
2293 if let Some(_guar) = guar {
2294 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2297
2298 return Ok(a_var);
2301 }
2302 }
2303
2304 let mut err = self.dcx().struct_span_err(sp, msg);
2305
2306 if self.token.is_ident()
2307 || (self.token == TokenKind::Pound
2308 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2309 {
2310 err.span_suggestion(
2313 sp,
2314 "try adding a comma",
2315 ",",
2316 Applicability::MachineApplicable,
2317 );
2318 err.emit();
2319 } else {
2320 return Err(err);
2321 }
2322 }
2323 }
2324 Ok(a_var)
2325 }
2326
2327 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2328 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)) {
2329 let sm = self.psess.source_map();
2330 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2331 let semi_typo = self.token == token::Semi
2332 && self.look_ahead(1, |t| {
2333 t.is_path_start()
2334 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2337 (Ok(l), Ok(r)) => l.line == r.line,
2338 _ => true,
2339 }
2340 });
2341 if eq_typo || semi_typo {
2342 self.bump();
2343 err.with_span_suggestion_short(
2345 self.prev_token.span,
2346 "field names and their types are separated with `:`",
2347 ":",
2348 Applicability::MachineApplicable,
2349 )
2350 .emit();
2351 } else {
2352 return Err(err);
2353 }
2354 }
2355 Ok(())
2356 }
2357
2358 fn parse_name_and_ty(
2360 &mut self,
2361 adt_ty: &str,
2362 lo: Span,
2363 vis: Visibility,
2364 mut_restriction: MutRestriction,
2365 safety: Safety,
2366 attrs: AttrVec,
2367 ) -> PResult<'a, FieldDef> {
2368 let name = self.parse_field_ident(adt_ty, lo)?;
2369 if self.token == token::Bang {
2370 if let Err(mut err) = self.unexpected() {
2371 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2373 return Err(err);
2374 }
2375 }
2376 self.expect_field_ty_separator()?;
2377 let ty = self.parse_ty()?;
2378 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2379 return Err(self
2380 .dcx()
2381 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2382 .with_span_suggestion_verbose(
2383 self.token.span,
2384 "write a path separator here",
2385 "::",
2386 Applicability::MaybeIncorrect,
2387 ));
2388 }
2389 let default = if self.token == token::Eq {
2390 self.bump();
2391 let const_expr = self.parse_expr_anon_const()?;
2392 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2393 self.psess.gated_spans.gate(sym::default_field_values, sp);
2394 Some(const_expr)
2395 } else {
2396 None
2397 };
2398 Ok(FieldDef {
2399 span: lo.to(self.prev_token.span),
2400 ident: Some(name),
2401 vis,
2402 extras: Self::field_def_extras(safety, mut_restriction, default),
2403 id: DUMMY_NODE_ID,
2404 ty,
2405 attrs,
2406 is_placeholder: false,
2407 })
2408 }
2409
2410 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2413 let (ident, is_raw) = self.ident_or_err(true)?;
2414 if is_raw == IdentIsRaw::No
2415 && ident.is_reserved()
2416 && !(ident.name == kw::Underscore && adt_ty == "enum")
2417 {
2418 let snapshot = self.create_snapshot_for_diagnostic();
2419 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2420 let inherited_vis = Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited };
2421 let fn_parse_mode =
2423 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2424 match self.parse_fn(
2425 &mut AttrVec::new(),
2426 fn_parse_mode,
2427 lo,
2428 &inherited_vis,
2429 Case::Insensitive,
2430 ) {
2431 Ok(_) => self
2432 .dcx()
2433 .struct_span_err(
2434 lo.to(self.prev_token.span),
2435 ::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"),
2436 )
2437 .with_help(
2438 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2439 )
2440 .with_help(
2441 "see https://doc.rust-lang.org/book/ch05-03-method-syntax.html \
2442 for more information",
2443 ),
2444 Err(err) => {
2445 err.cancel();
2446 self.restore_snapshot(snapshot);
2447 self.expected_ident_found_err()
2448 }
2449 }
2450 } 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)) {
2451 match self.parse_item_struct() {
2452 Ok(item) => {
2453 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2454 self.dcx()
2455 .struct_span_err(
2456 lo.with_hi(ident.span.hi()),
2457 ::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"),
2458 )
2459 .with_help(
2460 "consider creating a new `struct` definition instead of nesting",
2461 )
2462 }
2463 Err(err) => {
2464 err.cancel();
2465 self.restore_snapshot(snapshot);
2466 self.expected_ident_found_err()
2467 }
2468 }
2469 } else {
2470 let mut err = self.expected_ident_found_err();
2471 if self.eat_keyword_noexpect(kw::Let)
2472 && let removal_span = self.prev_token.span.until(self.token.span)
2473 && let Ok(ident) = self
2474 .parse_ident_common(false)
2475 .map_err(|err| err.cancel())
2477 && self.token == TokenKind::Colon
2478 {
2479 err.span_suggestion_verbose(
2480 removal_span,
2481 "remove the `let` keyword",
2482 String::new(),
2483 Applicability::MachineApplicable,
2484 );
2485 err.note("the `let` keyword is not allowed in `struct` fields");
2486 err.note(
2487 "see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> \
2488 for more information",
2489 );
2490 err.emit();
2491 return Ok(ident);
2492 } else {
2493 self.restore_snapshot(snapshot);
2494 }
2495 err
2496 };
2497 return Err(err);
2498 }
2499 self.bump();
2500 Ok(ident)
2501 }
2502
2503 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2511 let ident = self.parse_ident()?;
2512 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)) {
2513 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)) {
2515 let params = self.parse_token_tree(); let pspan = params.span();
2517 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2518 self.unexpected()?;
2519 }
2520 let body = self.parse_token_tree(); let bspan = body.span();
2523 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]);
2525 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2526 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2527 } else {
2528 self.unexpected_any()?
2529 };
2530
2531 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2532 Ok(ItemKind::MacroDef(
2533 ident,
2534 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2535 ))
2536 }
2537
2538 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2540 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)) {
2541 let macro_rules_span = self.token.span;
2542
2543 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2544 return IsMacroRulesItem::Yes { has_bang: true };
2545 } else if self.look_ahead(1, |t| t.is_ident()) {
2546 self.dcx().emit_err(diagnostics::MacroRulesMissingBang {
2548 span: macro_rules_span,
2549 hi: macro_rules_span.shrink_to_hi(),
2550 });
2551
2552 return IsMacroRulesItem::Yes { has_bang: false };
2553 }
2554 }
2555
2556 IsMacroRulesItem::No
2557 }
2558
2559 fn parse_item_macro_rules(
2561 &mut self,
2562 vis: &Visibility,
2563 has_bang: bool,
2564 ) -> PResult<'a, ItemKind> {
2565 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 {
2568 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2570 let ident = self.parse_ident()?;
2571
2572 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2573 let span = self.prev_token.span;
2575 self.dcx().emit_err(diagnostics::MacroNameRemoveBang { span });
2576 }
2577
2578 let body = self.parse_delim_args()?;
2579 self.eat_semi_for_macro_if_needed(&body, None);
2580 self.complain_if_pub_macro(vis, true);
2581
2582 Ok(ItemKind::MacroDef(
2583 ident,
2584 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2585 ))
2586 }
2587
2588 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2591 if let VisibilityKind::Inherited = vis.kind {
2592 return;
2593 }
2594
2595 let vstr = pprust::vis_to_string(vis);
2596 let vstr = vstr.trim_end();
2597 if macro_rules {
2598 self.dcx().emit_err(diagnostics::MacroRulesVisibility { span: vis.span, vis: vstr });
2599 } else {
2600 self.dcx()
2601 .emit_err(diagnostics::MacroInvocationVisibility { span: vis.span, vis: vstr });
2602 }
2603 }
2604
2605 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
2606 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)) {
2607 self.report_invalid_macro_expansion_item(args, path);
2608 }
2609 }
2610
2611 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
2612 let span = args.dspan.entire();
2613 let mut err = self.dcx().struct_span_err(
2614 span,
2615 "macros that expand to items must be delimited with braces or followed by a semicolon",
2616 );
2617 if !span.from_expansion() {
2620 let DelimSpan { open, close } = args.dspan;
2621 if let Some(path) = path
2624 && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2625 && args.delim == Delimiter::Parenthesis
2626 {
2627 let replace =
2628 if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2629 err.multipart_suggestion(
2630 "to define a macro, remove the parentheses around the macro name",
2631 ::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())],
2632 Applicability::MachineApplicable,
2633 );
2634 } else {
2635 err.multipart_suggestion(
2636 "change the delimiters to curly braces",
2637 ::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())],
2638 Applicability::MaybeIncorrect,
2639 );
2640 err.span_suggestion_verbose(
2641 span.with_neighbor(self.token.span).shrink_to_hi(),
2642 "add a semicolon",
2643 ';',
2644 Applicability::MaybeIncorrect,
2645 );
2646 }
2647 }
2648 err.emit();
2649 }
2650
2651 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2654 if (self.token.is_keyword(kw::Enum)
2655 || self.token.is_keyword(kw::Struct)
2656 || self.token.is_keyword(kw::Union))
2657 && self.look_ahead(1, |t| t.is_ident())
2658 {
2659 let kw_token = self.token;
2660 let kw_str = pprust::token_to_string(&kw_token);
2661 let item = self.parse_item(
2662 ForceCollect::No,
2663 AllowConstBlockItems::DoesNotMatter, )?;
2665 let mut item = item.unwrap().span;
2666 if self.token == token::Comma {
2667 item = item.to(self.token.span);
2668 }
2669 self.dcx().emit_err(diagnostics::NestedAdt {
2670 span: kw_token.span,
2671 item,
2672 kw_str,
2673 keyword: keyword.as_str(),
2674 });
2675 return Ok(false);
2677 }
2678 Ok(true)
2679 }
2680
2681 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2682 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2683 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)) {
2686 return true;
2687 }
2688 let mut i = 0;
2689 while i < ALL_QUALS.len() {
2690 let action = self.look_ahead(i + look_ahead, |token| {
2691 if token.is_keyword(kw::Impl) {
2692 return Some(true);
2693 }
2694 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2695 return None;
2697 }
2698 Some(false)
2699 });
2700 if let Some(ret) = action {
2701 return ret;
2702 }
2703 i += 1;
2704 }
2705
2706 self.is_keyword_ahead(i, &[kw::Impl])
2707 }
2708
2709 fn try_recover_const_missing_semi(
2717 &mut self,
2718 rhs: &Option<Box<Expr>>,
2719 const_span: Span,
2720 ) -> Option<Box<Expr>> {
2721 if self.token == TokenKind::Semi {
2722 return None;
2723 }
2724 let Some(rhs) = rhs else {
2725 return None;
2726 };
2727 if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
2728 return None;
2729 }
2730 if let Some((span, guar)) =
2731 self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
2732 {
2733 self.fn_body_missing_semi_guar = Some(guar);
2734 Some(self.mk_expr(span, ExprKind::Err(guar)))
2735 } else {
2736 None
2737 }
2738 }
2739}
2740enum IsMacroRulesItem {
2741 Yes { has_bang: bool },
2742 No,
2743}