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 /rustc-dev/4b6d04e706108ccfeafe2547fbe857dfe8972bad/compiler/rustc_parse/src/parser/item.rs:317",
"rustc_parse::parser::item", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/4b6d04e706108ccfeafe2547fbe857dfe8972bad/compiler/rustc_parse/src/parser/item.rs"),
::tracing_core::__macro_support::Option::Some(317u32),
::tracing_core::__macro_support::Option::Some("rustc_parse::parser::item"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Parsing a const block item that does not matter: {0:?}",
self.token.span) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("Parsing a const block item that does not matter: {:?}", self.token.span);
318 };
319 ItemKind::ConstBlock(self.parse_const_block_item()?)
320 } else if let Const::Yes(const_span) = self.parse_constness(case) {
321 self.recover_const_mut(const_span);
323 self.recover_missing_kw_before_item()?;
324 let (ident, generics, ty, body) = self.parse_const_item(const_span)?;
325 ItemKind::Const(Box::new(ConstItem {
326 defaultness: def_(),
327 ident,
328 generics,
329 ty,
330 body,
331 define_opaque: None,
332 }))
333 } else if let Some(kind) = self.is_reuse_item() {
334 self.parse_item_delegation(attrs, def_(), kind)?
335 } else if self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mod,
token_type: crate::parser::token_type::TokenType::KwMod,
}exp!(Mod), case)
336 || self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe), case) && self.is_keyword_ahead(1, &[kw::Mod])
337 {
338 self.parse_item_mod(attrs)?
340 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Type,
token_type: crate::parser::token_type::TokenType::KwType,
}exp!(Type), case) {
341 self.parse_type_alias(def_())?
343 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Enum,
token_type: crate::parser::token_type::TokenType::KwEnum,
}exp!(Enum), case) {
344 self.parse_item_enum()?
346 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Struct,
token_type: crate::parser::token_type::TokenType::KwStruct,
}exp!(Struct), case) {
347 self.parse_item_struct()?
349 } else if self.is_kw_followed_by_ident(kw::Union) {
350 self.bump(); self.parse_item_union()?
353 } else if self.is_builtin() {
354 return self.parse_item_builtin();
356 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Macro,
token_type: crate::parser::token_type::TokenType::KwMacro,
}exp!(Macro), case) {
357 self.parse_item_decl_macro(lo)?
359 } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
360 self.parse_item_macro_rules(vis, has_bang)?
362 } else if self.isnt_macro_invocation()
363 && (self.token.is_ident_named(sym::import)
364 || self.token.is_ident_named(sym::using)
365 || self.token.is_ident_named(sym::include)
366 || self.token.is_ident_named(sym::require))
367 {
368 return self.recover_import_as_use();
369 } else if self.isnt_macro_invocation() && vis.kind.is_pub() {
370 self.recover_missing_kw_before_item()?;
371 return Ok(None);
372 } else if self.isnt_macro_invocation() && case == Case::Sensitive {
373 _ = def_;
374
375 return self.parse_item_kind(
377 attrs,
378 macros_allowed,
379 allow_const_block_items,
380 lo,
381 vis,
382 def,
383 fn_parse_mode,
384 Case::Insensitive,
385 );
386 } else if macros_allowed && self.check_path() {
387 if self.isnt_macro_invocation() {
388 self.recover_missing_kw_before_item()?;
389 }
390 ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
392 } else {
393 return Ok(None);
394 };
395 Ok(Some(info))
396 }
397
398 fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
399 let span = self.token.span;
400 let token_name = super::token_descr(&self.token);
401 let snapshot = self.create_snapshot_for_diagnostic();
402 self.bump();
403 match self.parse_use_item() {
404 Ok(u) => {
405 self.dcx().emit_err(diagnostics::RecoverImportAsUse { span, token_name });
406 Ok(Some(u))
407 }
408 Err(e) => {
409 e.cancel();
410 self.restore_snapshot(snapshot);
411 Ok(None)
412 }
413 }
414 }
415
416 fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
417 let use_token_span = self.prev_token.span;
418 let tree = self.parse_use_tree(use_token_span, None)?;
419 if let Err(mut e) = self.expect_semi() {
420 match tree.kind {
421 UseTreeKind::Glob(_) => {
422 e.note("the wildcard token must be last on the path");
423 }
424 UseTreeKind::Nested { .. } => {
425 e.note("glob-like brace syntax must be last on the path");
426 }
427 _ => (),
428 }
429 return Err(e);
430 }
431 Ok(ItemKind::Use(tree))
432 }
433
434 pub(super) fn is_path_start_item(&mut self) -> bool {
436 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{..}) }
442
443 fn is_reuse_item(&mut self) -> Option<ReuseKind> {
444 if !self.token.is_keyword(kw::Reuse) {
445 return None;
446 }
447
448 if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
450 Some(ReuseKind::Path)
451 } else if self.check_impl_frontmatter(1) {
452 Some(ReuseKind::Impl)
453 } else {
454 None
455 }
456 }
457
458 fn isnt_macro_invocation(&mut self) -> bool {
460 self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
461 }
462
463 fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
466 let is_pub = self.prev_token.is_keyword(kw::Pub);
467 let is_const = self.prev_token.is_keyword(kw::Const);
468 let ident_span = self.token.span;
469 let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };
470 let insert_span = ident_span.shrink_to_lo();
471
472 let ident = if self.token.is_ident()
473 && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
474 && self.look_ahead(1, |t| {
475 #[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)
476 }) {
477 self.parse_ident_common(true).unwrap()
478 } else {
479 return Ok(());
480 };
481
482 let mut found_generics = false;
483 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Lt,
token_type: crate::parser::token_type::TokenType::Lt,
}exp!(Lt)) {
484 found_generics = true;
485 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Gt,
token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)]);
486 self.bump(); }
488
489 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)) {
490 if self.look_ahead(1, |t| *t == token::CloseBrace) {
492 Some(diagnostics::MissingKeywordForItemDefinition::EnumOrStruct { span })
494 } else if self.look_ahead(2, |t| *t == token::Colon)
495 || self.look_ahead(3, |t| *t == token::Colon)
496 {
497 Some(diagnostics::MissingKeywordForItemDefinition::Struct {
499 span,
500 insert_span,
501 ident,
502 })
503 } else {
504 Some(diagnostics::MissingKeywordForItemDefinition::Enum {
505 span,
506 insert_span,
507 ident,
508 })
509 }
510 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
511 self.bump(); let is_method = self.recover_self_param();
514
515 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);
516
517 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)) {
518 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)]);
519 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);
521 if is_method {
522 diagnostics::MissingKeywordForItemDefinition::Method {
523 span,
524 insert_span,
525 ident,
526 }
527 } else {
528 diagnostics::MissingKeywordForItemDefinition::Function {
529 span,
530 insert_span,
531 ident,
532 }
533 }
534 } 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)) {
535 diagnostics::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
536 } else {
537 diagnostics::MissingKeywordForItemDefinition::Ambiguous {
538 span,
539 subdiag: if found_generics {
540 None
541 } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
542 Some(diagnostics::AmbiguousMissingKwForItemSub::SuggestMacro {
543 span: ident_span,
544 snippet,
545 })
546 } else {
547 Some(diagnostics::AmbiguousMissingKwForItemSub::HelpMacro)
548 },
549 }
550 };
551 Some(err)
552 } else if found_generics {
553 Some(diagnostics::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
554 } else {
555 None
556 };
557
558 if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
559 }
560
561 fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
562 Ok(None)
564 }
565
566 fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
568 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() {
571 Ok(args) => {
573 self.eat_semi_for_macro_if_needed(&args, Some(&path));
574 self.complain_if_pub_macro(vis, false);
575 Ok(MacCall { path, args })
576 }
577
578 Err(mut err) => {
579 if self.token.is_ident()
581 && let [segment] = path.segments.as_slice()
582 && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
583 {
584 err.span_suggestion_verbose(
585 path.span,
586 "perhaps you meant to define a macro",
587 "macro_rules",
588 Applicability::MachineApplicable,
589 );
590 }
591 Err(err)
592 }
593 }
594 }
595
596 fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
598 let ([start @ end] | [start, .., end]) = attrs else {
599 return Ok(());
600 };
601 let msg = if end.is_doc_comment() {
602 "expected item after doc comment"
603 } else {
604 "expected item after attributes"
605 };
606 let mut err = self.dcx().struct_span_err(end.span, msg);
607 if end.is_doc_comment() {
608 err.span_label(end.span, "this doc comment doesn't document anything");
609 } else {
610 err.span_label(end.span, "expected an item after this");
611 if self.token == TokenKind::Semi {
612 err.span_suggestion_verbose(
613 self.token.span,
614 "remove the semicolon after the attribute",
615 "",
616 Applicability::MaybeIncorrect,
617 );
618 }
619 }
620 if let [.., penultimate, _] = attrs {
621 err.span_label(start.span.to(penultimate.span), "other attributes here");
622 }
623 Err(err)
624 }
625
626 fn is_async_fn(&self) -> bool {
627 self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
628 }
629
630 fn parse_polarity(&mut self) -> ast::ImplPolarity {
631 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()) {
633 self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
634 self.bump(); ast::ImplPolarity::Negative(self.prev_token.span)
636 } else {
637 ast::ImplPolarity::Positive
638 }
639 }
640
641 fn parse_item_impl(
656 &mut self,
657 attrs: &mut AttrVec,
658 defaultness: Defaultness,
659 is_reuse: bool,
660 ) -> PResult<'a, ItemKind> {
661 let constness = self.parse_constness(Case::Sensitive);
662 let safety = self.parse_safety(Case::Sensitive);
663 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
664 let mut generics_snapshot = None;
665 let mut generics = if self.choose_generics_over_qpath(0) {
667 self.parse_generics()?
668 } else {
669 if self.look_ahead(0, |t| t == &token::Lt)
672 && self.look_ahead(1, |t| t.is_ident())
673 && self.look_ahead(2, |t| t == &token::Lt)
674 {
675 generics_snapshot = Some(self.create_snapshot_for_diagnostic());
676 }
677
678 let mut generics = Generics::default();
679 generics.span = self.prev_token.span.shrink_to_hi();
682 generics
683 };
684
685 if let Const::Yes(span) = constness {
686 self.psess.gated_spans.gate(sym::const_trait_impl, span);
687 }
688
689 if (self.token_uninterpolated_span().at_least_rust_2018()
691 && self.token.is_keyword(kw::Async))
692 || self.is_kw_followed_by_ident(kw::Async)
693 {
694 self.bump();
695 self.dcx().emit_err(diagnostics::AsyncImpl { span: self.prev_token.span });
696 }
697
698 let polarity = self.parse_polarity();
699
700 let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
702 {
703 let span = self.prev_token.span.between(self.token.span);
704 return Err(self.dcx().create_err(diagnostics::MissingTraitInTraitImpl {
705 span,
706 for_span: span.to(self.token.span),
707 }));
708 } else {
709 self.parse_ty_with_generics_recovery(&generics).map_err(|e| {
710 let Some(mut snapshot) = generics_snapshot else {
711 return e;
712 };
713 snapshot.maybe_type_in_generic_parameter(e)
714 })?
715 };
716 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));
718 let missing_for_span = self.prev_token.span.between(self.token.span);
719
720 let ty_second = if self.token == token::DotDot {
721 self.bump(); Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
728 } else if has_for || self.token.can_begin_type() {
729 Some(self.parse_ty()?)
730 } else {
731 None
732 };
733
734 generics.where_clause = self.parse_where_clause()?;
735
736 let impl_items = if is_reuse {
737 Default::default()
738 } else {
739 self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
740 };
741
742 let (of_trait, self_ty) = match ty_second {
743 Some(ty_second) => {
744 if !has_for {
746 self.dcx()
747 .emit_err(diagnostics::MissingForInTraitImpl { span: missing_for_span });
748 }
749
750 let ty_first = *ty_first;
751 let path = match ty_first.kind {
752 TyKind::Path(None, path) => path,
754 other => {
755 if let TyKind::ImplTrait(_, bounds) = other
756 && let [bound] = bounds.as_slice()
757 && let GenericBound::Trait(poly_trait_ref) = bound
758 {
759 let extra_impl_kw = ty_first.span.until(bound.span());
763 self.dcx().emit_err(diagnostics::ExtraImplKeywordInTraitImpl {
764 extra_impl_kw,
765 impl_trait_span: ty_first.span,
766 });
767 poly_trait_ref.trait_ref.path.clone()
768 } else {
769 return Err(self.dcx().create_err(
770 diagnostics::ExpectedTraitInTraitImplFoundType {
771 span: ty_first.span,
772 },
773 ));
774 }
775 }
776 };
777 let trait_ref = TraitRef { path, ref_id: ty_first.id };
778
779 let of_trait =
780 Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
781 (of_trait, ty_second)
782 }
783 None => {
784 let self_ty = ty_first;
785 let error = |modifier, modifier_name, modifier_span| {
786 self.dcx().create_err(diagnostics::TraitImplModifierInInherentImpl {
787 span: self_ty.span,
788 modifier,
789 modifier_name,
790 modifier_span,
791 self_ty: self_ty.span,
792 })
793 };
794
795 if let Safety::Unsafe(span) = safety {
796 error("unsafe", "unsafe", span).with_code(E0197).emit();
797 }
798 if let ImplPolarity::Negative(span) = polarity {
799 error("!", "negative", span).emit();
800 }
801 if let Defaultness::Default(def_span) = defaultness {
802 error("default", "default", def_span).emit();
803 }
804 if let Const::Yes(span) = constness {
805 self.psess.gated_spans.gate(sym::const_trait_impl, span);
806 }
807 (None, self_ty)
808 }
809 };
810
811 Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
812 }
813
814 fn parse_item_delegation(
815 &mut self,
816 attrs: &mut AttrVec,
817 defaultness: Defaultness,
818 kind: ReuseKind,
819 ) -> PResult<'a, ItemKind> {
820 let span = self.token.span;
821 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Reuse,
token_type: crate::parser::token_type::TokenType::KwReuse,
}exp!(Reuse))?;
822
823 let item_kind = match kind {
824 ReuseKind::Path => self.parse_path_like_delegation(),
825 ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
826 }?;
827
828 self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
829
830 Ok(item_kind)
831 }
832
833 fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
834 Ok(if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
835 Some(self.parse_block()?)
836 } else {
837 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))?;
838 None
839 })
840 }
841
842 fn parse_impl_delegation(
843 &mut self,
844 span: Span,
845 attrs: &mut AttrVec,
846 defaultness: Defaultness,
847 ) -> PResult<'a, ItemKind> {
848 let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
849 let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
850
851 let until_expr_span = span.to(self.prev_token.span);
852
853 let Some(of_trait) = of_trait else {
854 return Err(self
855 .dcx()
856 .create_err(diagnostics::ImplReuseInherentImpl { span: until_expr_span }));
857 };
858
859 let body = self.parse_delegation_body()?;
860 let whole_reuse_span = span.to(self.prev_token.span);
861
862 items.push(Box::new(AssocItem {
863 id: DUMMY_NODE_ID,
864 attrs: Default::default(),
865 span: whole_reuse_span,
866 tokens: None,
867 vis: Visibility { kind: VisibilityKind::Inherited, span: whole_reuse_span },
868 kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
869 qself: None,
870 prefix: of_trait.trait_ref.path.clone(),
871 suffixes: DelegationSuffixes::Glob(whole_reuse_span),
872 body,
873 })),
874 }));
875
876 Ok(impl_item)
877 }
878
879 fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
880 let (qself, path) = if self.eat_lt() {
881 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
882 (Some(qself), path)
883 } else {
884 (None, self.parse_path(PathStyle::Expr)?)
885 };
886
887 let rename = |this: &mut Self| {
888 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 })
889 };
890
891 Ok(if self.eat_path_sep() {
892 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)) {
893 DelegationSuffixes::Glob(self.prev_token.span)
894 } else {
895 let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
896 DelegationSuffixes::List(
897 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,
898 )
899 };
900
901 ItemKind::DelegationMac(Box::new(DelegationMac {
902 qself,
903 prefix: path,
904 suffixes,
905 body: self.parse_delegation_body()?,
906 }))
907 } else {
908 let rename = rename(self)?;
909 let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
910
911 ItemKind::Delegation(Box::new(Delegation {
912 id: DUMMY_NODE_ID,
913 qself,
914 path,
915 ident,
916 rename,
917 body: self.parse_delegation_body()?,
918 source: DelegationSource::Single,
919 }))
920 })
921 }
922
923 fn parse_item_list<T>(
924 &mut self,
925 attrs: &mut AttrVec,
926 mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
927 ) -> PResult<'a, ThinVec<T>> {
928 let open_brace_span = self.token.span;
929
930 if self.token == TokenKind::Semi {
932 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
933 self.bump();
934 return Ok(ThinVec::new());
935 }
936
937 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
938 attrs.extend(self.parse_inner_attributes()?);
939
940 let mut items = ThinVec::new();
941 while !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)) {
942 if self.recover_doc_comment_before_brace() {
943 continue;
944 }
945 self.recover_vcs_conflict_marker();
946 match parse_item(self) {
947 Ok(None) => {
948 let mut is_unnecessary_semicolon = (self.token == token::Semi
949 && self.prev_token == token::Semi)
950 || !items.is_empty()
951 && self
969 .span_to_snippet(self.prev_token.span)
970 .is_ok_and(|snippet| snippet == "}")
971 && self.token == token::Semi;
972 let mut semicolon_span = self.token.span;
973 if !is_unnecessary_semicolon {
974 is_unnecessary_semicolon =
976 self.token == token::OpenBrace && self.prev_token == token::Semi;
977 semicolon_span = self.prev_token.span;
978 }
979 let non_item_span = self.token.span;
981 let is_let = self.token.is_keyword(kw::Let);
982
983 let mut err =
984 self.dcx().struct_span_err(non_item_span, "non-item in item list");
985 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);
986 if is_let {
987 err.span_suggestion_verbose(
988 non_item_span,
989 "consider using `const` instead of `let` for associated const",
990 "const",
991 Applicability::MachineApplicable,
992 );
993 } else {
994 err.span_label(open_brace_span, "item list starts here")
995 .span_label(non_item_span, "non-item starts here")
996 .span_label(self.prev_token.span, "item list ends here");
997 }
998 if is_unnecessary_semicolon {
999 err.span_suggestion_verbose(
1000 semicolon_span,
1001 "consider removing this semicolon",
1002 "",
1003 Applicability::MaybeIncorrect,
1004 );
1005 }
1006 err.emit();
1007 break;
1008 }
1009 Ok(Some(item)) => items.extend(item),
1010 Err(err) => {
1011 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);
1012 err.with_span_label(
1013 open_brace_span,
1014 "while parsing this item list starting here",
1015 )
1016 .with_span_label(self.prev_token.span, "the item list ends here")
1017 .emit();
1018 break;
1019 }
1020 }
1021 }
1022 Ok(items)
1023 }
1024
1025 fn recover_doc_comment_before_brace(&mut self) -> bool {
1027 if let token::DocComment(..) = self.token.kind {
1028 if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
1029 {
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!(
1031 self.dcx(),
1032 self.token.span,
1033 E0584,
1034 "found a documentation comment that doesn't document anything",
1035 )
1036 .with_span_label(self.token.span, "this doc comment doesn't document anything")
1037 .with_help(
1038 "doc comments must come before what they document, if a comment was \
1039 intended use `//`",
1040 )
1041 .emit();
1042 self.bump();
1043 return true;
1044 }
1045 }
1046 false
1047 }
1048
1049 fn parse_defaultness(&mut self) -> Defaultness {
1051 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))
1055 && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
1056 {
1057 self.psess.gated_spans.gate(sym::specialization, self.token.span);
1058 self.bump(); Defaultness::Default(self.prev_token_uninterpolated_span())
1060 } 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)) {
1061 self.psess.gated_spans.gate(sym::final_associated_functions, self.prev_token.span);
1062 Defaultness::Final(self.prev_token_uninterpolated_span())
1063 } else {
1064 Defaultness::Implicit
1065 }
1066 }
1067
1068 fn check_trait_front_matter(&mut self) -> bool {
1070 const SUFFIXES: &[&[Symbol]] = &[
1071 &[kw::Trait],
1072 &[kw::Auto, kw::Trait],
1073 &[kw::Unsafe, kw::Trait],
1074 &[kw::Unsafe, kw::Auto, kw::Trait],
1075 &[kw::Const, kw::Trait],
1076 &[kw::Const, kw::Auto, kw::Trait],
1077 &[kw::Const, kw::Unsafe, kw::Trait],
1078 &[kw::Const, kw::Unsafe, kw::Auto, kw::Trait],
1079 ];
1080 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) {
1082 if self.is_keyword_ahead(2, &[kw::In]) {
1084 return true;
1085 }
1086 if self.is_keyword_ahead(2, &[kw::Crate, kw::SelfLower, kw::Super])
1088 && self.look_ahead(3, |t| t == &token::CloseParen)
1089 && SUFFIXES.iter().any(|suffix| {
1090 suffix.iter().enumerate().all(|(i, kw)| self.is_keyword_ahead(i + 4, &[*kw]))
1091 })
1092 {
1093 return true;
1094 }
1095 SUFFIXES.iter().any(|suffix| {
1097 suffix.iter().enumerate().all(|(i, kw)| {
1098 self.tree_look_ahead(i + 2, |t| {
1099 if let TokenTree::Token(token, _) = t {
1100 token.is_keyword(*kw)
1101 } else {
1102 false
1103 }
1104 })
1105 .unwrap_or(false)
1106 })
1107 })
1108 } else {
1109 SUFFIXES.iter().any(|suffix| {
1110 suffix.iter().enumerate().all(|(i, kw)| {
1111 if i == 0 {
1113 match *kw {
1114 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)),
1115 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)),
1116 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)),
1117 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)),
1118 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1119 }
1120 } else {
1121 self.is_keyword_ahead(i, &[*kw])
1122 }
1123 })
1124 })
1125 }
1126 }
1127
1128 fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
1130 let impl_restriction = self.parse_impl_restriction()?;
1131 let constness = self.parse_constness(Case::Sensitive);
1132 if let Const::Yes(span) = constness {
1133 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1134 }
1135 let safety = self.parse_safety(Case::Sensitive);
1136 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)) {
1138 self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
1139 IsAuto::Yes
1140 } else {
1141 IsAuto::No
1142 };
1143
1144 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait))?;
1145 let ident = self.parse_ident()?;
1146 let mut generics = self.parse_generics()?;
1147
1148 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));
1150 let span_at_colon = self.prev_token.span;
1151 let bounds = if had_colon { self.parse_generic_bounds()? } else { ThinVec::new() };
1152
1153 let span_before_eq = self.prev_token.span;
1154 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1155 if had_colon {
1157 let span = span_at_colon.to(span_before_eq);
1158 self.dcx().emit_err(diagnostics::BoundsNotAllowedOnTraitAliases { span });
1159 }
1160
1161 let bounds = self.parse_generic_bounds()?;
1162 generics.where_clause = self.parse_where_clause()?;
1163 self.expect_semi()?;
1164
1165 let whole_span = lo.to(self.prev_token.span);
1166 if is_auto == IsAuto::Yes {
1167 self.dcx().emit_err(diagnostics::TraitAliasCannotBeAuto { span: whole_span });
1168 }
1169 if let Safety::Unsafe(_) = safety {
1170 self.dcx().emit_err(diagnostics::TraitAliasCannotBeUnsafe { span: whole_span });
1171 }
1172 if let RestrictionKind::Restricted { .. } = impl_restriction.kind {
1173 self.dcx()
1174 .emit_err(diagnostics::TraitAliasCannotBeImplRestricted { span: whole_span });
1175 }
1176
1177 self.psess.gated_spans.gate(sym::trait_alias, whole_span);
1178
1179 Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
1180 } else {
1181 generics.where_clause = self.parse_where_clause()?;
1183 let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
1184 Ok(ItemKind::Trait(Box::new(Trait {
1185 impl_restriction,
1186 constness,
1187 is_auto,
1188 safety,
1189 ident,
1190 generics,
1191 bounds,
1192 items,
1193 })))
1194 }
1195 }
1196
1197 pub fn parse_impl_item(
1198 &mut self,
1199 force_collect: ForceCollect,
1200 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1201 let fn_parse_mode =
1202 FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
1203 self.parse_assoc_item(fn_parse_mode, force_collect)
1204 }
1205
1206 pub fn parse_trait_item(
1207 &mut self,
1208 force_collect: ForceCollect,
1209 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1210 let fn_parse_mode = FnParseMode {
1211 req_name: |edition, _| edition >= Edition::Edition2018,
1212 context: FnContext::Trait,
1213 req_body: false,
1214 };
1215 self.parse_assoc_item(fn_parse_mode, force_collect)
1216 }
1217
1218 fn parse_assoc_item(
1220 &mut self,
1221 fn_parse_mode: FnParseMode,
1222 force_collect: ForceCollect,
1223 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1224 Ok(self
1225 .parse_item_(
1226 fn_parse_mode,
1227 force_collect,
1228 AllowConstBlockItems::DoesNotMatter, )?
1230 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1231 let kind = match AssocItemKind::try_from(kind) {
1232 Ok(kind) => kind,
1233 Err(kind) => match kind {
1234 ItemKind::Static(StaticItem {
1235 ident,
1236 ty,
1237 safety: _,
1238 mutability: _,
1239 expr,
1240 define_opaque,
1241 eii_impl: _,
1242 }) => {
1243 self.dcx()
1244 .emit_err(diagnostics::AssociatedStaticItemNotAllowed { span });
1245 AssocItemKind::Const(Box::new(ConstItem {
1246 defaultness: Defaultness::Implicit,
1247 ident,
1248 generics: Generics::default(),
1249 ty,
1250 body: expr,
1251 define_opaque,
1252 }))
1253 }
1254 _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
1255 },
1256 };
1257 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1258 }))
1259 }
1260
1261 fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
1267 let ident = self.parse_ident()?;
1268 let mut generics = self.parse_generics()?;
1269
1270 let bounds =
1272 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() };
1273 generics.where_clause = self.parse_where_clause()?;
1274
1275 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 };
1276
1277 let after_where_clause = self.parse_where_clause()?;
1278
1279 self.expect_semi()?;
1280
1281 Ok(ItemKind::TyAlias(Box::new(TyAlias {
1282 defaultness,
1283 ident,
1284 generics,
1285 after_where_clause,
1286 bounds,
1287 ty,
1288 })))
1289 }
1290
1291 fn parse_use_tree<'b>(
1301 &mut self,
1302 use_token_span: Span,
1303 use_path: Option<&'b UsePathList<'b>>,
1304 ) -> PResult<'a, UseTree> {
1305 let lo = self.token.span;
1306
1307 let mut prefix = ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo() };
1308 let kind =
1309 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() {
1310 let mod_sep_ctxt = self.token.span.ctxt();
1312 if self.eat_path_sep() {
1313 prefix
1314 .segments
1315 .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
1316 }
1317
1318 self.parse_use_tree_glob_or_nested(use_token_span, use_path)?
1319 } else {
1320 prefix = self.parse_path(PathStyle::Mod)?;
1322
1323 if self.eat_path_sep() {
1324 let use_path = UsePathList { elements: &prefix.segments, prev: use_path };
1325 self.parse_use_tree_glob_or_nested(use_token_span, Some(&use_path))?
1326 } else {
1327 while self.eat_noexpect(&token::Colon) {
1329 self.dcx().emit_err(diagnostics::SingleColonImportPath {
1330 span: self.prev_token.span,
1331 });
1332
1333 self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
1335 prefix.span = lo.to(self.prev_token.span);
1336 }
1337
1338 UseTreeKind::Simple(self.parse_rename()?)
1339 }
1340 };
1341
1342 Ok(UseTree { prefix, kind })
1343 }
1344
1345 fn parse_use_tree_glob_or_nested<'b>(
1347 &mut self,
1348 use_token_span: Span,
1349 use_path: Option<&'b UsePathList<'b>>,
1350 ) -> PResult<'a, UseTreeKind> {
1351 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
1352 UseTreeKind::Glob(self.prev_token.span)
1353 } else {
1354 let lo = self.token.span;
1355 UseTreeKind::Nested {
1356 items: self.parse_use_tree_list(use_token_span, use_path)?,
1357 span: lo.to(self.prev_token.span),
1358 }
1359 })
1360 }
1361
1362 fn parse_use_tree_list<'b>(
1368 &mut self,
1369 use_token_span: Span,
1370 prefix: Option<&'b UsePathList<'b>>,
1371 ) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
1372 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| {
1373 p.recover_vcs_conflict_marker();
1374
1375 let mut attr_span = None;
1376 let attrs = p.parse_outer_attributes()?;
1377 if !attrs.is_empty() {
1378 let raw_attrs = attrs.take_for_recovery(&p.psess);
1379 attr_span =
1380 Some(raw_attrs.first().unwrap().span.to(raw_attrs.last().unwrap().span));
1381 }
1382
1383 let use_tree = p.parse_use_tree(use_token_span, prefix)?;
1384
1385 if let Some(attr_span) = attr_span {
1386 p.emit_error_attr_in_use_tree(use_token_span, prefix, use_tree.span(), attr_span);
1387 }
1388
1389 Ok((use_tree, DUMMY_NODE_ID))
1390 })
1391 .map(|(r, _)| r)
1392 }
1393
1394 fn emit_error_attr_in_use_tree(
1395 &self,
1396 use_token_span: Span,
1397 mut prefix: Option<&UsePathList<'_>>,
1398 use_tree_span: Span,
1399 attr_span: Span,
1400 ) {
1401 let Ok(attr) = self.psess.source_map().span_to_snippet(attr_span) else { return };
1402
1403 let prefix: Vec<_> = {
1404 let mut tmp = Vec::new();
1405 while let Some(prefix_) = prefix {
1406 tmp.push(prefix_.elements);
1407 prefix = prefix_.prev;
1408 }
1409 tmp.reverse();
1410 tmp.into_iter().flatten().collect()
1411 };
1412
1413 let prefix: String = prefix
1414 .iter()
1415 .map(|seg| if seg.ident.name == kw::PathRoot { "" } else { seg.ident.as_str() })
1416 .intersperse("::")
1417 .collect();
1418
1419 let mut comma_reached = false;
1420 let Ok(tree_span) = self.psess.source_map().span_extend_while(use_tree_span, |c| {
1421 if comma_reached {
1422 return false;
1423 }
1424 comma_reached = c == ',';
1425 c.is_whitespace() || comma_reached
1426 }) else {
1427 return;
1428 };
1429
1430 let Ok(use_tree) = self.psess.source_map().span_to_snippet(use_tree_span) else { return };
1431
1432 let code = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}\nuse {1}::{2};\n", attr,
prefix, use_tree))
})format!("{attr}\nuse {prefix}::{use_tree};\n");
1434
1435 self.dcx().emit_err(crate::diagnostics::AttrInUseTree {
1436 attr_span,
1437 sub: Some(crate::diagnostics::AttrInUseTreeSugg {
1438 use_lo: use_token_span.shrink_to_lo(),
1439 attr_span,
1440 tree_span,
1441 code,
1442 }),
1443 });
1444 }
1445
1446 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1447 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)) {
1448 self.parse_ident_or_underscore().map(Some)
1449 } else {
1450 Ok(None)
1451 }
1452 }
1453
1454 fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
1455 match self.token.ident() {
1456 Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
1457 self.bump();
1458 Ok(ident)
1459 }
1460 _ => self.parse_ident(),
1461 }
1462 }
1463
1464 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1473 let orig_ident = self.parse_crate_name_with_dashes()?;
1475 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1476 (Some(orig_ident.name), rename)
1477 } else {
1478 (None, orig_ident)
1479 };
1480 self.expect_semi()?;
1481 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1482 }
1483
1484 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1485 let ident = if self.token.is_keyword(kw::SelfLower) {
1486 self.parse_path_segment_ident()
1487 } else {
1488 self.parse_ident()
1489 }?;
1490
1491 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1492 if self.token != dash.tok {
1493 return Ok(ident);
1494 }
1495
1496 let mut dashes = ::alloc::vec::Vec::new()vec![];
1498 let mut idents = ::alloc::vec::Vec::new()vec![];
1499 while self.eat(dash) {
1500 dashes.push(self.prev_token.span);
1501 idents.push(self.parse_ident()?);
1502 }
1503
1504 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1505 let mut fixed_name = ident.name.to_string();
1506 for part in idents {
1507 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1508 }
1509
1510 self.dcx().emit_err(diagnostics::ExternCrateNameWithDashes {
1511 span: fixed_name_sp,
1512 sugg: diagnostics::ExternCrateNameWithDashesSugg { dashes },
1513 });
1514
1515 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1516 }
1517
1518 fn parse_item_foreign_mod(
1529 &mut self,
1530 attrs: &mut AttrVec,
1531 mut safety: Safety,
1532 ) -> PResult<'a, ItemKind> {
1533 let extern_span = self.prev_token_uninterpolated_span();
1534 let abi = self.parse_abi(); if safety == Safety::Default
1537 && self.token.is_keyword(kw::Unsafe)
1538 && self.look_ahead(1, |t| *t == token::OpenBrace)
1539 {
1540 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();
1541 safety = Safety::Unsafe(self.token.span);
1542 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));
1543 }
1544 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1545 extern_span,
1546 safety,
1547 abi,
1548 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1549 }))
1550 }
1551
1552 pub fn parse_foreign_item(
1554 &mut self,
1555 force_collect: ForceCollect,
1556 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1557 let fn_parse_mode = FnParseMode {
1558 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1559 context: FnContext::Free,
1560 req_body: false,
1561 };
1562 Ok(self
1563 .parse_item_(
1564 fn_parse_mode,
1565 force_collect,
1566 AllowConstBlockItems::DoesNotMatter, )?
1568 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1569 let kind = match ForeignItemKind::try_from(kind) {
1570 Ok(kind) => kind,
1571 Err(kind) => match kind {
1572 ItemKind::Const(ConstItem { ident, ty, body, .. }) => {
1573 let const_span = Some(span.with_hi(ident.span.lo()))
1574 .filter(|span| span.can_be_used_for_suggestions());
1575 self.dcx().emit_err(diagnostics::ExternItemCannotBeConst {
1576 ident_span: ident.span,
1577 const_span,
1578 });
1579 ForeignItemKind::Static(Box::new(StaticItem {
1580 ident,
1581 ty,
1582 mutability: Mutability::Not,
1583 expr: body,
1584 safety: Safety::Default,
1585 define_opaque: None,
1586 eii_impl: None,
1587 }))
1588 }
1589 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1590 },
1591 };
1592 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1593 }))
1594 }
1595
1596 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1597 let span = self.psess.source_map().guess_head_span(span);
1599 let descr = kind.descr();
1600 let help = match kind {
1601 ItemKind::DelegationMac(DelegationMac {
1602 suffixes: DelegationSuffixes::Glob(_),
1603 ..
1604 }) => false,
1605 _ => true,
1606 };
1607 self.dcx().emit_err(diagnostics::BadItemKind { span, descr, ctx, help });
1608 None
1609 }
1610
1611 fn is_use_closure(&self) -> bool {
1612 if self.token.is_keyword(kw::Use) {
1613 self.look_ahead(1, |token| {
1615 let dist =
1617 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1618
1619 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))
1620 })
1621 } else {
1622 false
1623 }
1624 }
1625
1626 pub(super) fn is_unsafe_foreign_mod(&self) -> bool {
1627 if !self.token.is_keyword(kw::Unsafe) {
1629 return false;
1630 }
1631 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1633 return false;
1634 }
1635
1636 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1638
1639 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, _)))
1644 == Some(true)
1645 }
1646
1647 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1648 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) {
1649 !self.look_ahead(1, |token| {
1651 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1652 return true;
1653 }
1654 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1655 })
1656 } else {
1657 (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)
1659 || 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))
1660 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1661 };
1662
1663 if is_global_static {
1664 let safety = self.parse_safety(case);
1665 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);
1666 Some(safety)
1667 } else {
1668 None
1669 }
1670 }
1671
1672 fn recover_const_mut(&mut self, const_span: Span) {
1674 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)) {
1675 let span = self.prev_token.span;
1676 self.dcx()
1677 .emit_err(diagnostics::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1678 } 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)) {
1679 let span = self.prev_token.span;
1680 self.dcx()
1681 .emit_err(diagnostics::ConstLetMutuallyExclusive { span: const_span.to(span) });
1682 }
1683 }
1684
1685 fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
1686 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1687 let const_span = self.prev_token.span;
1688 self.psess.gated_spans.gate(sym::const_block_items, const_span);
1689 let block = self.parse_block()?;
1690 Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
1691 }
1692
1693 fn parse_static_item(
1700 &mut self,
1701 safety: Safety,
1702 mutability: Mutability,
1703 ) -> PResult<'a, ItemKind> {
1704 let ident = self.parse_ident()?;
1705
1706 if self.token == TokenKind::Lt && self.may_recover() {
1707 let generics = self.parse_generics()?;
1708 self.dcx().emit_err(diagnostics::StaticWithGenerics { span: generics.span });
1709 }
1710
1711 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))) {
1714 (true, false) => self.parse_ty()?,
1715 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1718 };
1719
1720 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 };
1721
1722 self.expect_semi()?;
1723
1724 let item =
1725 StaticItem { ident, ty, safety, mutability, expr, define_opaque: None, eii_impl: None };
1726 Ok(ItemKind::Static(Box::new(item)))
1727 }
1728
1729 fn parse_const_item(
1738 &mut self,
1739 const_span: Span,
1740 ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<Box<Expr>>)> {
1741 let ident = self.parse_ident_or_underscore()?;
1742
1743 let mut generics = self.parse_generics()?;
1744
1745 if !generics.span.is_empty() {
1748 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1749 }
1750
1751 let ty = match (
1754 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1755 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)),
1756 ) {
1757 (true, false) => self.parse_ty()?,
1758 (colon, _) => self.recover_missing_global_item_type(colon, None),
1760 };
1761
1762 let before_where_clause =
1765 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1766
1767 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 };
1768
1769 let after_where_clause = self.parse_where_clause()?;
1770
1771 if before_where_clause.has_where_token
1775 && let Some(rhs) = &rhs
1776 {
1777 self.dcx().emit_err(diagnostics::WhereClauseBeforeConstBody {
1778 span: before_where_clause.span,
1779 name: ident.span,
1780 body: rhs.span,
1781 sugg: if !after_where_clause.has_where_token {
1782 self.psess.source_map().span_to_snippet(rhs.span).ok().map(|body_s| {
1783 diagnostics::WhereClauseBeforeConstBodySugg {
1784 left: before_where_clause.span.shrink_to_lo(),
1785 snippet: body_s,
1786 right: before_where_clause.span.shrink_to_hi().to(rhs.span),
1787 }
1788 })
1789 } else {
1790 None
1793 },
1794 });
1795 }
1796
1797 let mut predicates = before_where_clause.predicates;
1804 predicates.extend(after_where_clause.predicates);
1805 let where_clause = WhereClause {
1806 has_where_token: before_where_clause.has_where_token
1807 || after_where_clause.has_where_token,
1808 predicates,
1809 span: if after_where_clause.has_where_token {
1810 after_where_clause.span
1811 } else {
1812 before_where_clause.span
1813 },
1814 };
1815
1816 if where_clause.has_where_token {
1817 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1818 }
1819
1820 generics.where_clause = where_clause;
1821
1822 if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
1823 return Ok((ident, generics, ty, Some(rhs)));
1824 }
1825 self.expect_semi()?;
1826
1827 Ok((ident, generics, ty, rhs))
1828 }
1829
1830 fn recover_missing_global_item_type(
1833 &mut self,
1834 colon_present: bool,
1835 m: Option<Mutability>,
1836 ) -> Box<Ty> {
1837 let kind = match m {
1840 Some(Mutability::Mut) => "static mut",
1841 Some(Mutability::Not) => "static",
1842 None => "const",
1843 };
1844
1845 let colon = match colon_present {
1846 true => "",
1847 false => ":",
1848 };
1849
1850 let span = self.prev_token.span.shrink_to_hi();
1851 let err = self.dcx().create_err(diagnostics::MissingConstType { span, colon, kind });
1852 err.stash(span, StashKey::ItemNoType);
1853
1854 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID })
1857 }
1858
1859 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1861 if self.token.is_keyword(kw::Struct) {
1862 let span = self.prev_token.span.to(self.token.span);
1863 let err = diagnostics::EnumStructMutuallyExclusive { span };
1864 if self.look_ahead(1, |t| t.is_ident()) {
1865 self.bump();
1866 self.dcx().emit_err(err);
1867 } else {
1868 return Err(self.dcx().create_err(err));
1869 }
1870 }
1871
1872 let prev_span = self.prev_token.span;
1873 let ident = self.parse_ident()?;
1874 let mut generics = self.parse_generics()?;
1875 generics.where_clause = self.parse_where_clause()?;
1876
1877 let (variants, _) = if self.token == TokenKind::Semi {
1879 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
1880 self.bump();
1881 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1882 } else {
1883 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| {
1884 p.parse_enum_variant(ident.span)
1885 })
1886 .map_err(|mut err| {
1887 err.span_label(ident.span, "while parsing this enum");
1888 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1890 let snapshot = self.create_snapshot_for_diagnostic();
1891 self.bump();
1892 match self.parse_ty() {
1893 Ok(_) => {
1894 err.span_suggestion_verbose(
1895 prev_span,
1896 "perhaps you meant to use `struct` here",
1897 "struct",
1898 Applicability::MaybeIncorrect,
1899 );
1900 }
1901 Err(e) => {
1902 e.cancel();
1903 }
1904 }
1905 self.restore_snapshot(snapshot);
1906 }
1907 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1908 self.bump(); err
1910 })?
1911 };
1912
1913 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1914 Ok(ItemKind::Enum(ident, generics, enum_definition))
1915 }
1916
1917 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1918 self.recover_vcs_conflict_marker();
1919 let variant_attrs = self.parse_outer_attributes()?;
1920 self.recover_vcs_conflict_marker();
1921 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1922 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1923 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1924 let vlo = this.token.span;
1925
1926 let vis = this.parse_visibility(FollowedByType::No)?;
1927 if !this.recover_nested_adt_item(kw::Enum)? {
1928 return Ok((None, Trailing::No, UsePreAttrPos::No));
1929 }
1930 let ident = this.parse_field_ident("enum", vlo)?;
1931
1932 if this.token == token::Bang {
1933 if let Err(err) = this.unexpected() {
1934 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();
1935 }
1936
1937 this.bump();
1938 this.parse_delim_args()?;
1939
1940 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1941 }
1942
1943 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)) {
1944 let (fields, recovered) =
1946 match this.parse_record_struct_body("struct", ident.span, false) {
1947 Ok((fields, recovered)) => (fields, recovered),
1948 Err(mut err) => {
1949 if this.token == token::Colon {
1950 return Err(err);
1952 }
1953 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1954 this.bump(); err.span_label(span, "while parsing this enum");
1956 err.help(help);
1957 let guar = err.emit();
1958 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1959 }
1960 };
1961 VariantData::Struct { fields, recovered }
1962 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1963 let body = match this.parse_tuple_struct_body() {
1964 Ok(body) => body,
1965 Err(mut err) => {
1966 if this.token == token::Colon {
1967 return Err(err);
1969 }
1970 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
1971 this.bump(); err.span_label(span, "while parsing this enum");
1973 err.help(help);
1974 err.emit();
1975 ::thin_vec::ThinVec::new()thin_vec![]
1976 }
1977 };
1978 VariantData::Tuple(body, DUMMY_NODE_ID)
1979 } else {
1980 VariantData::Unit(DUMMY_NODE_ID)
1981 };
1982
1983 let disr_expr =
1984 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 };
1985
1986 let span = vlo.to(this.prev_token.span);
1987 if ident.name == kw::Underscore {
1988 this.psess.gated_spans.gate(sym::unnamed_enum_variants, span);
1989 }
1990 let vr = ast::Variant {
1991 ident,
1992 vis,
1993 id: DUMMY_NODE_ID,
1994 attrs: variant_attrs,
1995 data: struct_def,
1996 disr_expr,
1997 span,
1998 is_placeholder: false,
1999 };
2000
2001 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
2002 })
2003 .map_err(|mut err| {
2004 err.help(help);
2005 err
2006 })
2007 }
2008
2009 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
2011 let ident = self.parse_ident()?;
2012
2013 let mut generics = self.parse_generics()?;
2014
2015 let vdata = if self.token.is_keyword(kw::Where) {
2030 let tuple_struct_body;
2031 (generics.where_clause, tuple_struct_body) =
2032 self.parse_struct_where_clause(ident, generics.span)?;
2033
2034 if let Some(body) = tuple_struct_body {
2035 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
2037 self.expect_semi()?;
2038 body
2039 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
2040 VariantData::Unit(DUMMY_NODE_ID)
2042 } else {
2043 let (fields, recovered) = self.parse_record_struct_body(
2045 "struct",
2046 ident.span,
2047 generics.where_clause.has_where_token,
2048 )?;
2049 VariantData::Struct { fields, recovered }
2050 }
2051 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
2053 VariantData::Unit(DUMMY_NODE_ID)
2054 } else if self.token == token::OpenBrace {
2056 let (fields, recovered) = self.parse_record_struct_body(
2057 "struct",
2058 ident.span,
2059 generics.where_clause.has_where_token,
2060 )?;
2061 VariantData::Struct { fields, recovered }
2062 } else if self.token == token::OpenParen {
2064 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
2065 generics.where_clause = self.parse_where_clause()?;
2066 self.expect_semi()?;
2067 body
2068 } else {
2069 let err = diagnostics::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
2070 return Err(self.dcx().create_err(err));
2071 };
2072
2073 Ok(ItemKind::Struct(ident, generics, vdata))
2074 }
2075
2076 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
2078 let ident = self.parse_ident()?;
2079
2080 let mut generics = self.parse_generics()?;
2081
2082 let vdata = if self.token.is_keyword(kw::Where) {
2083 generics.where_clause = self.parse_where_clause()?;
2084 let (fields, recovered) = self.parse_record_struct_body(
2085 "union",
2086 ident.span,
2087 generics.where_clause.has_where_token,
2088 )?;
2089 VariantData::Struct { fields, recovered }
2090 } else if self.token == token::OpenBrace {
2091 let (fields, recovered) = self.parse_record_struct_body(
2092 "union",
2093 ident.span,
2094 generics.where_clause.has_where_token,
2095 )?;
2096 VariantData::Struct { fields, recovered }
2097 } else {
2098 let token_str = super::token_descr(&self.token);
2099 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}");
2100 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2101 err.span_label(self.token.span, "expected `where` or `{` after union name");
2102 return Err(err);
2103 };
2104
2105 Ok(ItemKind::Union(ident, generics, vdata))
2106 }
2107
2108 pub(crate) fn parse_record_struct_body(
2113 &mut self,
2114 adt_ty: &str,
2115 ident_span: Span,
2116 parsed_where: bool,
2117 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
2118 let mut fields = ThinVec::new();
2119 let mut recovered = Recovered::No;
2120 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2121 while self.token != token::CloseBrace {
2122 match self.parse_field_def(adt_ty, ident_span) {
2123 Ok(field) => {
2124 fields.push(field);
2125 }
2126 Err(mut err) => {
2127 self.consume_block(
2128 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
2129 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
2130 ConsumeClosingDelim::No,
2131 );
2132 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}"));
2133 let guar = err.emit();
2134 recovered = Recovered::Yes(guar);
2135 break;
2136 }
2137 }
2138 }
2139 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
2140 } else {
2141 let token_str = super::token_descr(&self.token);
2142 let where_str = if parsed_where { "" } else { "`where`, or " };
2143 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}");
2144 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2145 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",));
2146 return Err(err);
2147 }
2148
2149 Ok((fields, recovered))
2150 }
2151
2152 fn parse_unsafe_field(&mut self) -> Safety {
2153 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)) {
2155 let span = self.prev_token.span;
2156 self.psess.gated_spans.gate(sym::unsafe_fields, span);
2157 Safety::Unsafe(span)
2158 } else {
2159 Safety::Default
2160 }
2161 }
2162 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
2165 let openparen_span = self.token.span;
2166 let mut encountered_colon = false;
2167 self.parse_paren_comma_seq(|p| {
2168 let attrs = p.parse_outer_attributes()?;
2169 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
2170 let mut snapshot = None;
2171 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
2172 snapshot = Some(p.create_snapshot_for_diagnostic());
2176 }
2177 let lo = p.token.span;
2178 let vis = match p.parse_visibility(FollowedByType::Yes) {
2179 Ok(vis) => vis,
2180 Err(err) => {
2181 if let Some(ref mut snapshot) = snapshot {
2182 snapshot.recover_vcs_conflict_marker();
2183 }
2184 return Err(err);
2185 }
2186 };
2187 let mut_restriction = p.parse_mut_restriction()?;
2188 encountered_colon |=
2189 p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
2190 let ty = match p.parse_ty() {
2193 Ok(ty) => ty,
2194 Err(err) => {
2195 if let Some(ref mut snapshot) = snapshot {
2196 snapshot.recover_vcs_conflict_marker();
2197 }
2198 return Err(err);
2199 }
2200 };
2201 let mut default = None;
2202 if p.token == token::Eq {
2203 let mut snapshot = p.create_snapshot_for_diagnostic();
2204 snapshot.bump();
2205 match snapshot.parse_expr_anon_const() {
2206 Ok(const_expr) => {
2207 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2208 p.psess.gated_spans.gate(sym::default_field_values, sp);
2209 p.restore_snapshot(snapshot);
2210 default = Some(const_expr);
2211 }
2212 Err(err) => {
2213 err.cancel();
2214 }
2215 }
2216 }
2217
2218 Ok((
2219 FieldDef {
2220 span: lo.to(ty.span),
2221 vis,
2222 extras: Self::field_def_extras(Safety::Default, mut_restriction, default),
2223 ident: None,
2224 id: DUMMY_NODE_ID,
2225 ty,
2226 attrs,
2227 is_placeholder: false,
2228 },
2229 Trailing::from(p.token == token::Comma),
2230 UsePreAttrPos::No,
2231 ))
2232 })
2233 })
2234 .map(|(r, _)| r)
2235 .map_err(|mut error| {
2236 if self.token == token::Colon {
2237 error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
2238 }
2239 if encountered_colon {
2240 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
2241 self.bump();
2242 error.subdiagnostic(UseRegularStructSuggestion {
2243 open: openparen_span,
2244 close: self.prev_token.span,
2245 semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
2246 });
2247 }
2248 error
2249 })
2250 }
2251
2252 fn field_def_extras(
2253 safety: Safety,
2254 mut_restriction: MutRestriction,
2255 default: Option<AnonConst>,
2256 ) -> Option<Box<FieldDefExtras>> {
2257 match (safety, mut_restriction, default) {
2258 (
2259 Safety::Default,
2260 MutRestriction { kind: RestrictionKind::Unrestricted, span: _ },
2263 None,
2264 ) => None,
2265 (safety, mut_restriction, default) => {
2266 Some(Box::new(FieldDefExtras { safety, mut_restriction, default }))
2267 }
2268 }
2269 }
2270
2271 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2273 self.recover_vcs_conflict_marker();
2274 let attrs = self.parse_outer_attributes()?;
2275 self.recover_vcs_conflict_marker();
2276 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2277 let lo = this.token.span;
2278 let vis = this.parse_visibility(FollowedByType::No)?;
2279 let mut_restriction = this.parse_mut_restriction()?;
2280 let safety = this.parse_unsafe_field();
2281 this.parse_single_struct_field(
2282 adt_ty,
2283 lo,
2284 vis,
2285 mut_restriction,
2286 safety,
2287 attrs,
2288 ident_span,
2289 )
2290 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2291 })
2292 }
2293
2294 fn parse_single_struct_field(
2296 &mut self,
2297 adt_ty: &str,
2298 lo: Span,
2299 vis: Visibility,
2300 mut_restriction: MutRestriction,
2301 safety: Safety,
2302 attrs: AttrVec,
2303 ident_span: Span,
2304 ) -> PResult<'a, FieldDef> {
2305 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, mut_restriction, safety, attrs)?;
2306 match self.token.kind {
2307 token::Comma => {
2308 self.bump();
2309 }
2310 token::Semi => {
2311 self.bump();
2312 let sp = self.prev_token.span;
2313 let mut err =
2314 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 `,`"));
2315 err.span_suggestion_short(
2316 sp,
2317 "replace `;` with `,`",
2318 ",",
2319 Applicability::MachineApplicable,
2320 );
2321 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}"));
2322 err.emit();
2323 }
2324 token::CloseBrace => {}
2325 token::DocComment(..) => {
2326 let previous_span = self.prev_token.span;
2327 let mut err = diagnostics::DocCommentDoesNotDocumentAnything {
2328 span: self.token.span,
2329 missing_comma: None,
2330 };
2331 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 {
2333 self.dcx().emit_err(err);
2334 } else {
2335 let sp = previous_span.shrink_to_hi();
2336 err.missing_comma = Some(sp);
2337 return Err(self.dcx().create_err(err));
2338 }
2339 }
2340 _ => {
2341 let sp = self.prev_token.span.shrink_to_hi();
2342 let msg =
2343 ::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));
2344
2345 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2347 && let Some(last_segment) = segments.last()
2348 {
2349 let guar = self.check_trailing_angle_brackets(
2350 last_segment,
2351 &[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)],
2352 );
2353 if let Some(_guar) = guar {
2354 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2357
2358 return Ok(a_var);
2361 }
2362 }
2363
2364 let mut err = self.dcx().struct_span_err(sp, msg);
2365
2366 if self.token.is_ident()
2367 || (self.token == TokenKind::Pound
2368 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2369 {
2370 err.span_suggestion(
2373 sp,
2374 "try adding a comma",
2375 ",",
2376 Applicability::MachineApplicable,
2377 );
2378 err.emit();
2379 } else {
2380 return Err(err);
2381 }
2382 }
2383 }
2384 Ok(a_var)
2385 }
2386
2387 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2388 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)) {
2389 let sm = self.psess.source_map();
2390 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2391 let semi_typo = self.token == token::Semi
2392 && self.look_ahead(1, |t| {
2393 t.is_path_start()
2394 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2397 (Ok(l), Ok(r)) => l.line == r.line,
2398 _ => true,
2399 }
2400 });
2401 if eq_typo || semi_typo {
2402 self.bump();
2403 err.with_span_suggestion_short(
2405 self.prev_token.span,
2406 "field names and their types are separated with `:`",
2407 ":",
2408 Applicability::MachineApplicable,
2409 )
2410 .emit();
2411 } else {
2412 return Err(err);
2413 }
2414 }
2415 Ok(())
2416 }
2417
2418 fn parse_name_and_ty(
2420 &mut self,
2421 adt_ty: &str,
2422 lo: Span,
2423 vis: Visibility,
2424 mut_restriction: MutRestriction,
2425 safety: Safety,
2426 attrs: AttrVec,
2427 ) -> PResult<'a, FieldDef> {
2428 let name = self.parse_field_ident(adt_ty, lo)?;
2429 if self.token == token::Bang {
2430 if let Err(mut err) = self.unexpected() {
2431 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2433 return Err(err);
2434 }
2435 }
2436 self.expect_field_ty_separator()?;
2437 let ty = self.parse_ty()?;
2438 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2439 return Err(self
2440 .dcx()
2441 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2442 .with_span_suggestion_verbose(
2443 self.token.span,
2444 "write a path separator here",
2445 "::",
2446 Applicability::MaybeIncorrect,
2447 ));
2448 }
2449 let default = if self.token == token::Eq {
2450 self.bump();
2451 let const_expr = self.parse_expr_anon_const()?;
2452 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2453 self.psess.gated_spans.gate(sym::default_field_values, sp);
2454 Some(const_expr)
2455 } else {
2456 None
2457 };
2458 Ok(FieldDef {
2459 span: lo.to(self.prev_token.span),
2460 ident: Some(name),
2461 vis,
2462 extras: Self::field_def_extras(safety, mut_restriction, default),
2463 id: DUMMY_NODE_ID,
2464 ty,
2465 attrs,
2466 is_placeholder: false,
2467 })
2468 }
2469
2470 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2473 let (ident, is_raw) = self.ident_or_err(true)?;
2474 if is_raw == IdentIsRaw::No
2475 && ident.is_reserved()
2476 && !(ident.name == kw::Underscore && adt_ty == "enum")
2477 {
2478 let snapshot = self.create_snapshot_for_diagnostic();
2479 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2480 let inherited_vis = Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited };
2481 let fn_parse_mode =
2483 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2484 match self.parse_fn(
2485 &mut AttrVec::new(),
2486 fn_parse_mode,
2487 lo,
2488 &inherited_vis,
2489 Case::Insensitive,
2490 ) {
2491 Ok(_) => self
2492 .dcx()
2493 .struct_span_err(
2494 lo.to(self.prev_token.span),
2495 ::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"),
2496 )
2497 .with_help(
2498 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2499 )
2500 .with_help(
2501 "see https://doc.rust-lang.org/book/ch05-03-method-syntax.html \
2502 for more information",
2503 ),
2504 Err(err) => {
2505 err.cancel();
2506 self.restore_snapshot(snapshot);
2507 self.expected_ident_found_err()
2508 }
2509 }
2510 } 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)) {
2511 match self.parse_item_struct() {
2512 Ok(item) => {
2513 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2514 self.dcx()
2515 .struct_span_err(
2516 lo.with_hi(ident.span.hi()),
2517 ::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"),
2518 )
2519 .with_help(
2520 "consider creating a new `struct` definition instead of nesting",
2521 )
2522 }
2523 Err(err) => {
2524 err.cancel();
2525 self.restore_snapshot(snapshot);
2526 self.expected_ident_found_err()
2527 }
2528 }
2529 } else {
2530 let mut err = self.expected_ident_found_err();
2531 if self.eat_keyword_noexpect(kw::Let)
2532 && let removal_span = self.prev_token.span.until(self.token.span)
2533 && let Ok(ident) = self
2534 .parse_ident_common(false)
2535 .map_err(|err| err.cancel())
2537 && self.token == TokenKind::Colon
2538 {
2539 err.span_suggestion_verbose(
2540 removal_span,
2541 "remove the `let` keyword",
2542 String::new(),
2543 Applicability::MachineApplicable,
2544 );
2545 err.note("the `let` keyword is not allowed in `struct` fields");
2546 err.note(
2547 "see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> \
2548 for more information",
2549 );
2550 err.emit();
2551 return Ok(ident);
2552 } else {
2553 self.restore_snapshot(snapshot);
2554 }
2555 err
2556 };
2557 return Err(err);
2558 }
2559 self.bump();
2560 Ok(ident)
2561 }
2562
2563 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2571 let ident = self.parse_ident()?;
2572 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)) {
2573 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)) {
2575 let params = self.parse_token_tree(); let pspan = params.span();
2577 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2578 self.unexpected()?;
2579 }
2580 let body = self.parse_token_tree(); let bspan = body.span();
2583 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]);
2585 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2586 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2587 } else {
2588 self.unexpected_any()?
2589 };
2590
2591 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2592 Ok(ItemKind::MacroDef(
2593 ident,
2594 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2595 ))
2596 }
2597
2598 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2600 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)) {
2601 let macro_rules_span = self.token.span;
2602
2603 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2604 return IsMacroRulesItem::Yes { has_bang: true };
2605 } else if self.look_ahead(1, |t| t.is_ident()) {
2606 self.dcx().emit_err(diagnostics::MacroRulesMissingBang {
2608 span: macro_rules_span,
2609 hi: macro_rules_span.shrink_to_hi(),
2610 });
2611
2612 return IsMacroRulesItem::Yes { has_bang: false };
2613 }
2614 }
2615
2616 IsMacroRulesItem::No
2617 }
2618
2619 fn parse_item_macro_rules(
2621 &mut self,
2622 vis: &Visibility,
2623 has_bang: bool,
2624 ) -> PResult<'a, ItemKind> {
2625 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 {
2628 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2630 let ident = self.parse_ident()?;
2631
2632 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2633 let span = self.prev_token.span;
2635 self.dcx().emit_err(diagnostics::MacroNameRemoveBang { span });
2636 }
2637
2638 let body = self.parse_delim_args()?;
2639 self.eat_semi_for_macro_if_needed(&body, None);
2640 self.complain_if_pub_macro(vis, true);
2641
2642 Ok(ItemKind::MacroDef(
2643 ident,
2644 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2645 ))
2646 }
2647
2648 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2651 if let VisibilityKind::Inherited = vis.kind {
2652 return;
2653 }
2654
2655 let vstr = pprust::vis_to_string(vis);
2656 let vstr = vstr.trim_end();
2657 if macro_rules {
2658 self.dcx().emit_err(diagnostics::MacroRulesVisibility { span: vis.span, vis: vstr });
2659 } else {
2660 self.dcx()
2661 .emit_err(diagnostics::MacroInvocationVisibility { span: vis.span, vis: vstr });
2662 }
2663 }
2664
2665 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
2666 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)) {
2667 self.report_invalid_macro_expansion_item(args, path);
2668 }
2669 }
2670
2671 pub fn parse_test_binder_constraints(&mut self) -> PResult<'a, Box<TestBinderConstraints>> {
2673 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
2674 let mut generics = self.parse_generics()?;
2675 generics.where_clause = self.parse_where_clause()?;
2676 let body = self.parse_test_binder_body()?;
2677 Ok(Box::new(TestBinderConstraints { generics, body: Box::new(body) }))
2678 }
2679
2680 pub fn parse_test_binder_body(&mut self) -> PResult<'a, TestBinderBody> {
2681 let mut foralls = ThinVec::new();
2682 let mut exists = ThinVec::new();
2683 let mut constraints = Vec::new();
2684 let mut predicates = Vec::new();
2685 self.parse_delim_comma_seq(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), |this| {
2686 if this.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Where,
token_type: crate::parser::token_type::TokenType::KwWhere,
}exp!(Where)) {
2687 predicates.push(this.parse_where_clause()?);
2688 return Ok(());
2689 }
2690 match this.token.ident() {
2691 Some((Ident { name: sym::forall, .. }, IdentIsRaw::No)) => {
2692 foralls.push(this.parse_test_binder_forall()?)
2693 }
2694 Some((Ident { name: sym::exists, .. }, IdentIsRaw::No)) => {
2695 exists.push(this.parse_test_binder_exists()?)
2696 }
2697
2698 _ => constraints.push(this.parse_test_binder_constraint()?),
2699 }
2700 Ok(())
2701 })?;
2702 Ok(TestBinderBody { foralls, exists, constraints, predicates })
2703 }
2704
2705 pub fn parse_test_binder_forall(&mut self) -> PResult<'a, TestBinderForall> {
2706 let span = self.token.span;
2707 self.bump();
2708
2709 let mut generics = self.parse_generics()?;
2710 generics.where_clause = self.parse_where_clause()?;
2711
2712 let body = self.parse_test_binder_body()?;
2713
2714 let assert_on_exit = if let Some((i, IdentIsRaw::No)) = self.token.ident()
2715 && i.name == sym::expect
2716 {
2717 self.bump();
2718 let items = self
2719 .parse_delim_comma_seq(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), |this| {
2720 this.parse_test_binder_constraint()
2721 })?
2722 .0;
2723 Some(items)
2724 } else {
2725 None
2726 };
2727
2728 Ok(TestBinderForall { span, node_id: DUMMY_NODE_ID, generics, body, assert_on_exit })
2729 }
2730
2731 pub fn parse_test_binder_exists(&mut self) -> PResult<'a, TestBinderExists> {
2732 let span = self.token.span;
2733 self.bump();
2734 let params = self.parse_generics()?.params;
2735 let body = self.parse_test_binder_body()?;
2736 Ok(TestBinderExists { span, node_id: DUMMY_NODE_ID, params, body })
2737 }
2738
2739 pub fn parse_test_binder_constraint(&mut self) -> PResult<'a, TestBinderConstraint> {
2740 match self.token.ident() {
2741 Some((Ident { name: sym::and, .. }, IdentIsRaw::No)) => {
2742 self.bump();
2743 let items = self
2744 .parse_delim_comma_seq(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), |this| {
2745 this.parse_test_binder_constraint()
2746 })?
2747 .0;
2748 Ok(TestBinderConstraint::And { items })
2749 }
2750 Some((Ident { name: sym::or, .. }, IdentIsRaw::No)) => {
2751 self.bump();
2752 let items = self
2753 .parse_delim_comma_seq(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), |this| {
2754 this.parse_test_binder_constraint()
2755 })?
2756 .0;
2757 Ok(TestBinderConstraint::Or { items })
2758 }
2759 _ if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::For,
token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For)) => {
2760 let bound_type_constraint = self.parse_test_binder_bound_type_constraint()?;
2761 Ok(TestBinderConstraint::AliasOutlives { bound_type_constraint })
2762 }
2763 _ if self.token.lifetime().is_some() => {
2764 let lhs = self.expect_lifetime();
2765 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon))?;
2766 if !self.check_lifetime() {
2767 self.unexpected()?;
2768 }
2769 let rhs = self.expect_lifetime();
2770 Ok(TestBinderConstraint::Lifetime { lhs, rhs })
2771 }
2772 _ if self.token.can_begin_type() => {
2773 let lhs = self.parse_ty_for_where_clause()?;
2774 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon))?;
2775 if !self.check_lifetime() {
2776 self.unexpected()?;
2777 }
2778 let rhs = self.expect_lifetime();
2779 Ok(TestBinderConstraint::PlaceholderOutlives { lhs, rhs })
2780 }
2781 _ => Err(self.dcx().struct_span_err(self.token.span, "unexpected token")),
2782 }
2783 }
2784
2785 fn parse_test_binder_bound_type_constraint(
2786 &mut self,
2787 ) -> PResult<'a, TestBinderBoundTypeConstraint> {
2788 let lo = self.token.span;
2789 let ast::WhereBoundPredicate { bound_generic_params, bounded_ty, bounds } =
2790 self.parse_ty_where_predicate_kind()?;
2791 let mut rhs = None;
2792 for bound in bounds {
2793 match bound {
2794 GenericBound::Trait(poly_trait_ref) => {
2795 self.dcx().span_err(poly_trait_ref.span, "trait bounds aren't supported here");
2796 }
2797 GenericBound::Use(_, span) => {
2798 self.dcx().span_err(span, "use bounds aren't supported here");
2799 }
2800 GenericBound::Outlives(lifetime) => {
2801 if rhs.is_some() {
2802 self.dcx().span_err(
2803 lifetime.ident.span,
2804 "only one lifetime on the rhs supported",
2805 );
2806 } else {
2807 rhs = Some(lifetime);
2808 }
2809 }
2810 }
2811 }
2812 match rhs {
2813 Some(rhs) => Ok(TestBinderBoundTypeConstraint {
2814 span: lo.to(self.prev_token.span),
2815 node_id: DUMMY_NODE_ID,
2816 params: bound_generic_params,
2817 lhs: bounded_ty,
2818 rhs,
2819 }),
2820 None => Err(self.dcx().struct_span_err(
2821 bounded_ty.span,
2822 "expected a single lifetime on the rhs of this constraint",
2823 )),
2824 }
2825 }
2826
2827 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
2828 let span = args.dspan.entire();
2829 let mut err = self.dcx().struct_span_err(
2830 span,
2831 "macros that expand to items must be delimited with braces or followed by a semicolon",
2832 );
2833 if !span.from_expansion() {
2836 let DelimSpan { open, close } = args.dspan;
2837 if let Some(path) = path
2840 && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2841 && args.delim == Delimiter::Parenthesis
2842 {
2843 let replace =
2844 if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2845 err.multipart_suggestion(
2846 "to define a macro, remove the parentheses around the macro name",
2847 ::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())],
2848 Applicability::MachineApplicable,
2849 );
2850 } else {
2851 err.multipart_suggestion(
2852 "change the delimiters to curly braces",
2853 ::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())],
2854 Applicability::MaybeIncorrect,
2855 );
2856 err.span_suggestion_verbose(
2857 span.with_neighbor(self.token.span).shrink_to_hi(),
2858 "add a semicolon",
2859 ';',
2860 Applicability::MaybeIncorrect,
2861 );
2862 }
2863 }
2864 err.emit();
2865 }
2866
2867 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2870 if (self.token.is_keyword(kw::Enum)
2871 || self.token.is_keyword(kw::Struct)
2872 || self.token.is_keyword(kw::Union))
2873 && self.look_ahead(1, |t| t.is_ident())
2874 {
2875 let kw_token = self.token;
2876 let kw_str = pprust::token_to_string(&kw_token);
2877 let item = self.parse_item(
2878 ForceCollect::No,
2879 AllowConstBlockItems::DoesNotMatter, )?;
2881 let mut item = item.unwrap().span;
2882 if self.token == token::Comma {
2883 item = item.to(self.token.span);
2884 }
2885 self.dcx().emit_err(diagnostics::NestedAdt {
2886 span: kw_token.span,
2887 item,
2888 kw_str,
2889 keyword: keyword.as_str(),
2890 });
2891 return Ok(false);
2893 }
2894 Ok(true)
2895 }
2896
2897 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2898 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2899 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)) {
2902 return true;
2903 }
2904 let mut i = 0;
2905 while i < ALL_QUALS.len() {
2906 let action = self.look_ahead(i + look_ahead, |token| {
2907 if token.is_keyword(kw::Impl) {
2908 return Some(true);
2909 }
2910 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2911 return None;
2913 }
2914 Some(false)
2915 });
2916 if let Some(ret) = action {
2917 return ret;
2918 }
2919 i += 1;
2920 }
2921
2922 self.is_keyword_ahead(i, &[kw::Impl])
2923 }
2924
2925 fn try_recover_const_missing_semi(
2933 &mut self,
2934 rhs: &Option<Box<Expr>>,
2935 const_span: Span,
2936 ) -> Option<Box<Expr>> {
2937 if self.token == TokenKind::Semi {
2938 return None;
2939 }
2940 let Some(rhs) = rhs else {
2941 return None;
2942 };
2943 if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
2944 return None;
2945 }
2946 if let Some((span, guar)) =
2947 self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
2948 {
2949 self.fn_body_missing_semi_guar = Some(guar);
2950 Some(self.mk_expr(span, ExprKind::Err(guar)))
2951 } else {
2952 None
2953 }
2954 }
2955}
2956
2957enum IsMacroRulesItem {
2958 Yes { has_bang: bool },
2959 No,
2960}
2961
2962struct UsePathList<'a> {
2963 elements: &'a [ast::PathSegment],
2964 prev: Option<&'a Self>,
2965}