1use std::fmt::Write;
2use std::mem;
3
4use ast::token::IdentKind;
5use rustc_ast as ast;
6use rustc_ast::ast::*;
7use rustc_ast::token::{self, Delimiter, MetaVarKind, TokenKind};
8use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
9use rustc_ast::util::case::Case;
10use rustc_ast_pretty::pprust;
11use rustc_errors::codes::*;
12use rustc_errors::{Applicability, PResult, StashKey, msg, struct_span_code_err};
13use rustc_span::edit_distance::edit_distance;
14use rustc_span::edition::Edition;
15use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
16use thin_vec::{ThinVec, thin_vec};
17use tracing::debug;
18
19use super::diagnostics::ConsumeClosingDelim;
20use super::{
21 AllowConstBlockItems, AttrWrapper, ExpTokenPair, FnContext, FnParseMode, FollowedByType,
22 ForceCollect, IsDotDotDot, Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,
23};
24use crate::diagnostics::{
25 self, MacroExpandsToAdtField, UseDoubleColonSuggestion, UseRegularStructSuggestion,
26};
27use crate::exp;
28
29impl<'a> Parser<'a> {
30 pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
32 let (attrs, items, spans) = self.parse_mod(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eof,
token_type: crate::parser::token_type::TokenType::Eof,
}exp!(Eof))?;
33 Ok(ast::Crate { attrs, items, spans, id: DUMMY_NODE_ID, is_placeholder: false })
34 }
35
36 fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
38 let safety = self.parse_safety(Case::Sensitive);
39 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mod,
token_type: crate::parser::token_type::TokenType::KwMod,
}exp!(Mod))?;
40 let ident = self.parse_ident()?;
41 let mod_kind = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
42 ModKind::Unloaded
43 } else {
44 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
45 let (inner_attrs, items, inner_span) = self.parse_mod(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
46 attrs.extend(inner_attrs);
47 ModKind::Loaded(items, Inline::Yes, inner_span)
48 };
49 Ok(ItemKind::Mod(safety, ident, mod_kind))
50 }
51
52 pub fn parse_mod(
57 &mut self,
58 term: ExpTokenPair,
59 ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
60 let lo = self.token.span;
61 let attrs = self.parse_inner_attributes()?;
62
63 let post_attr_lo = self.token.span;
64 let mut items: ThinVec<Box<_>> = ThinVec::new();
65
66 loop {
69 while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else {
71 break;
72 };
73 items.push(item);
74 }
75
76 if !self.eat(term) {
77 let token_str = super::token_descr(&self.token);
78 if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
79 let is_let = self.token.is_keyword(kw::Let);
80 let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
81 let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);
82
83 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected item, found {0}",
token_str))
})format!("expected item, found {token_str}");
84 let mut err = self.dcx().struct_span_err(self.token.span, msg);
85
86 let label = if is_let {
87 "`let` cannot be used for global variables"
88 } else {
89 "expected item"
90 };
91 err.span_label(self.token.span, label);
92
93 if is_let {
94 if is_let_mut {
95 err.help("consider using `static` and a `Mutex` instead of `let mut`");
96 } else if let_has_ident {
97 err.span_suggestion_short(
98 self.token.span,
99 "consider using `static` or `const` instead of `let`",
100 "static",
101 Applicability::MaybeIncorrect,
102 );
103 } else {
104 err.help("consider using `static` or `const` instead of `let`");
105 }
106 }
107 err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
108 return Err(err);
109 }
110 }
111
112 let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo());
113 let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };
114 Ok((attrs, items, mod_spans))
115 }
116}
117
118enum ReuseKind {
119 Path,
120 Impl,
121}
122
123impl<'a> Parser<'a> {
124 pub fn parse_item(
125 &mut self,
126 force_collect: ForceCollect,
127 allow_const_block_items: AllowConstBlockItems,
128 ) -> PResult<'a, Option<Box<Item>>> {
129 let fn_parse_mode =
130 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
131 self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items)
132 .map(|i| i.map(Box::new))
133 }
134
135 fn parse_item_(
136 &mut self,
137 fn_parse_mode: FnParseMode,
138 force_collect: ForceCollect,
139 const_block_items_allowed: AllowConstBlockItems,
140 ) -> PResult<'a, Option<Item>> {
141 self.recover_vcs_conflict_marker();
142 let attrs = self.parse_outer_attributes()?;
143 self.recover_vcs_conflict_marker();
144 self.parse_item_common(
145 attrs,
146 true,
147 false,
148 fn_parse_mode,
149 force_collect,
150 const_block_items_allowed,
151 )
152 }
153
154 pub(super) fn parse_item_common(
155 &mut self,
156 attrs: AttrWrapper,
157 mac_allowed: bool,
158 attrs_allowed: bool,
159 fn_parse_mode: FnParseMode,
160 force_collect: ForceCollect,
161 allow_const_block_items: AllowConstBlockItems,
162 ) -> PResult<'a, Option<Item>> {
163 if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| {
164 this.parse_item(ForceCollect::Yes, allow_const_block_items)
165 }) {
166 let mut item = item.expect("an actual item");
167 attrs.prepend_to_nt_inner(&mut item.attrs);
168 return Ok(Some(*item));
169 }
170
171 self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {
172 let lo = this.token.span;
173 let vis = this.parse_visibility(FollowedByType::No)?;
174 let mut def = this.parse_defaultness();
175 let kind = this.parse_item_kind(
176 &mut attrs,
177 mac_allowed,
178 allow_const_block_items,
179 lo,
180 &vis,
181 &mut def,
182 fn_parse_mode,
183 Case::Sensitive,
184 )?;
185 if let Some(kind) = kind {
186 this.error_on_unconsumed_default(def, &kind);
187 let span = lo.to(this.prev_token.span);
188 let id = DUMMY_NODE_ID;
189 let item = Item { attrs, id, kind, vis, span, tokens: None };
190 return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
191 }
192
193 if !#[allow(non_exhaustive_omitted_patterns)] match vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(vis.kind, VisibilityKind::Inherited) {
195 let vis_str = pprust::vis_to_string(&vis).trim_end().to_string();
196 let mut err = this.dcx().create_err(diagnostics::VisibilityNotFollowedByItem {
197 span: vis.span,
198 vis: vis_str,
199 });
200 if let Some((ident, _)) = this.token.ident()
201 && !ident.is_used_keyword()
202 && let Some((similar_kw, is_incorrect_case)) = ident
203 .name
204 .find_similar(&rustc_span::symbol::used_keywords(|| ident.span.edition()))
205 {
206 err.subdiagnostic(diagnostics::MisspelledKw {
207 similar_kw: similar_kw.to_string(),
208 span: ident.span,
209 is_incorrect_case,
210 });
211 }
212 err.emit();
213 }
214
215 if let Defaultness::Default(span) = def {
216 this.dcx().emit_err(diagnostics::DefaultNotFollowedByItem { span });
217 } else if let Defaultness::Final(span) = def {
218 this.dcx().emit_err(diagnostics::FinalNotFollowedByItem { span });
219 }
220
221 if !attrs_allowed {
222 this.recover_attrs_no_item(&attrs)?;
223 }
224 Ok((None, Trailing::No, UsePreAttrPos::No))
225 })
226 }
227
228 fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
230 match def {
231 Defaultness::Default(span) => {
232 self.dcx().emit_err(diagnostics::InappropriateDefault {
233 span,
234 article: kind.article(),
235 descr: kind.descr(),
236 });
237 }
238 Defaultness::Final(span) => {
239 self.dcx().emit_err(diagnostics::InappropriateFinal {
240 span,
241 article: kind.article(),
242 descr: kind.descr(),
243 });
244 }
245 Defaultness::Implicit => (),
246 }
247 }
248
249 fn parse_item_kind(
251 &mut self,
252 attrs: &mut AttrVec,
253 macros_allowed: bool,
254 allow_const_block_items: AllowConstBlockItems,
255 lo: Span,
256 vis: &Visibility,
257 def: &mut Defaultness,
258 fn_parse_mode: FnParseMode,
259 case: Case,
260 ) -> PResult<'a, Option<ItemKind>> {
261 let check_pub = def == &Defaultness::Implicit;
262 let mut def_ = || mem::replace(def, Defaultness::Implicit);
263
264 let info = if !self.is_use_closure() && self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Use,
token_type: crate::parser::token_type::TokenType::KwUse,
}exp!(Use), case) {
265 self.parse_use_item()?
266 } else if self.check_fn_front_matter(check_pub, case) {
267 let defaultness = def_();
269 if let Defaultness::Default(span) = defaultness {
270 self.psess.gated_spans.gate(sym::min_specialization, span);
274 self.psess.gated_spans.ungate_last(sym::specialization, span);
275 }
276 let (ident, sig, generics, contract, body) =
277 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
278 ItemKind::Fn(Box::new(Fn {
279 defaultness,
280 ident,
281 sig,
282 generics,
283 contract,
284 body,
285 define_opaque: None,
286 eii_impl: None,
287 }))
288 } else if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern), case) {
289 if self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Crate,
token_type: crate::parser::token_type::TokenType::KwCrate,
}exp!(Crate), case) {
290 self.parse_item_extern_crate()?
292 } else {
293 self.parse_item_foreign_mod(attrs, Safety::Default)?
295 }
296 } else if self.is_unsafe_foreign_mod() {
297 let safety = self.parse_safety(Case::Sensitive);
299 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern))?;
300 self.parse_item_foreign_mod(attrs, safety)?
301 } else if let Some(safety) = self.parse_global_static_front_matter(case) {
302 let mutability = self.parse_mutability();
304 self.parse_static_item(safety, mutability)?
305 } else if self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait), case) || self.check_trait_front_matter() {
306 self.parse_item_trait(attrs, lo)?
308 } else if self.check_impl_frontmatter(0) {
309 self.parse_item_impl(attrs, def_(), false)?
311 } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
312 allow_const_block_items
313 && self.check_inline_const(0)
314 {
315 if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
317 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/1303417c416e1595173d9689e7394c31e136ae95/compiler/rustc_parse/src/parser/item.rs:317",
"rustc_parse::parser::item", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1303417c416e1595173d9689e7394c31e136ae95/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.non_raw_ident().is_some_and(|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<UseTreeAndId>> {
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(UseTreeAndId { inner: use_tree, id: 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 if let Some(ident @ Ident { name: kw::Underscore, .. }) = self.token.non_raw_ident() {
1456 self.bump();
1457 Ok(ident)
1458 } else {
1459 self.parse_ident()
1460 }
1461 }
1462
1463 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1472 let orig_ident = self.parse_crate_name_with_dashes()?;
1474 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1475 (Some(orig_ident.name), rename)
1476 } else {
1477 (None, orig_ident)
1478 };
1479 self.expect_semi()?;
1480 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1481 }
1482
1483 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1484 let ident = if self.token.is_keyword(kw::SelfLower) {
1485 self.parse_path_segment_ident()
1486 } else {
1487 self.parse_ident()
1488 }?;
1489
1490 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1491 if self.token != dash.tok {
1492 return Ok(ident);
1493 }
1494
1495 let mut dashes = ::alloc::vec::Vec::new()vec![];
1497 let mut idents = ::alloc::vec::Vec::new()vec![];
1498 while self.eat(dash) {
1499 dashes.push(self.prev_token.span);
1500 idents.push(self.parse_ident()?);
1501 }
1502
1503 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1504 let mut fixed_name = ident.name.to_string();
1505 for part in idents {
1506 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1507 }
1508
1509 self.dcx().emit_err(diagnostics::ExternCrateNameWithDashes {
1510 span: fixed_name_sp,
1511 sugg: diagnostics::ExternCrateNameWithDashesSugg { dashes },
1512 });
1513
1514 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1515 }
1516
1517 fn parse_item_foreign_mod(
1528 &mut self,
1529 attrs: &mut AttrVec,
1530 mut safety: Safety,
1531 ) -> PResult<'a, ItemKind> {
1532 let extern_span = self.prev_token_uninterpolated_span();
1533 let abi = self.parse_abi(); if safety == Safety::Default
1536 && self.token.is_keyword(kw::Unsafe)
1537 && self.look_ahead(1, |t| *t == token::OpenBrace)
1538 {
1539 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();
1540 safety = Safety::Unsafe(self.token.span);
1541 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));
1542 }
1543 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1544 extern_span,
1545 safety,
1546 abi,
1547 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1548 }))
1549 }
1550
1551 pub fn parse_foreign_item(
1553 &mut self,
1554 force_collect: ForceCollect,
1555 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1556 let fn_parse_mode = FnParseMode {
1557 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1558 context: FnContext::Free,
1559 req_body: false,
1560 };
1561 Ok(self
1562 .parse_item_(
1563 fn_parse_mode,
1564 force_collect,
1565 AllowConstBlockItems::DoesNotMatter, )?
1567 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1568 let kind = match ForeignItemKind::try_from(kind) {
1569 Ok(kind) => kind,
1570 Err(kind) => match kind {
1571 ItemKind::Const(ConstItem { ident, ty, body, .. }) => {
1572 let const_span = Some(span.with_hi(ident.span.lo()))
1573 .filter(|span| span.can_be_used_for_suggestions());
1574 self.dcx().emit_err(diagnostics::ExternItemCannotBeConst {
1575 ident_span: ident.span,
1576 const_span,
1577 });
1578 ForeignItemKind::Static(Box::new(StaticItem {
1579 ident,
1580 ty,
1581 mutability: Mutability::Not,
1582 expr: body,
1583 safety: Safety::Default,
1584 define_opaque: None,
1585 eii_impl: None,
1586 }))
1587 }
1588 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1589 },
1590 };
1591 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1592 }))
1593 }
1594
1595 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1596 let span = self.psess.source_map().guess_head_span(span);
1598 let descr = kind.descr();
1599 let help = match kind {
1600 ItemKind::DelegationMac(DelegationMac {
1601 suffixes: DelegationSuffixes::Glob(_),
1602 ..
1603 }) => false,
1604 _ => true,
1605 };
1606 self.dcx().emit_err(diagnostics::BadItemKind { span, descr, ctx, help });
1607 None
1608 }
1609
1610 fn is_use_closure(&self) -> bool {
1611 if self.token.is_keyword(kw::Use) {
1612 self.look_ahead(1, |token| {
1614 let dist =
1616 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1617
1618 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))
1619 })
1620 } else {
1621 false
1622 }
1623 }
1624
1625 pub(super) fn is_unsafe_foreign_mod(&self) -> bool {
1626 if !self.token.is_keyword(kw::Unsafe) {
1628 return false;
1629 }
1630 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1632 return false;
1633 }
1634
1635 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1637
1638 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, _)))
1643 == Some(true)
1644 }
1645
1646 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1647 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) {
1648 !self.look_ahead(1, |token| {
1650 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1651 return true;
1652 }
1653 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1654 })
1655 } else {
1656 (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)
1658 || 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))
1659 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1660 };
1661
1662 if is_global_static {
1663 let safety = self.parse_safety(case);
1664 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);
1665 Some(safety)
1666 } else {
1667 None
1668 }
1669 }
1670
1671 fn recover_const_mut(&mut self, const_span: Span) {
1673 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)) {
1674 let span = self.prev_token.span;
1675 self.dcx()
1676 .emit_err(diagnostics::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1677 } 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)) {
1678 let span = self.prev_token.span;
1679 self.dcx()
1680 .emit_err(diagnostics::ConstLetMutuallyExclusive { span: const_span.to(span) });
1681 }
1682 }
1683
1684 fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
1685 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1686 let const_span = self.prev_token.span;
1687 self.psess.gated_spans.gate(sym::const_block_items, const_span);
1688 let block = self.parse_block()?;
1689 Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
1690 }
1691
1692 fn parse_static_item(
1699 &mut self,
1700 safety: Safety,
1701 mutability: Mutability,
1702 ) -> PResult<'a, ItemKind> {
1703 let ident = self.parse_ident()?;
1704
1705 if self.token == TokenKind::Lt && self.may_recover() {
1706 let generics = self.parse_generics()?;
1707 self.dcx().emit_err(diagnostics::StaticWithGenerics { span: generics.span });
1708 }
1709
1710 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))) {
1713 (true, false) => self.parse_ty()?,
1714 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1717 };
1718
1719 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 };
1720
1721 self.expect_semi()?;
1722
1723 let item =
1724 StaticItem { ident, ty, safety, mutability, expr, define_opaque: None, eii_impl: None };
1725 Ok(ItemKind::Static(Box::new(item)))
1726 }
1727
1728 fn parse_const_item(
1737 &mut self,
1738 const_span: Span,
1739 ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<Box<Expr>>)> {
1740 let ident = self.parse_ident_or_underscore()?;
1741
1742 let mut generics = self.parse_generics()?;
1743
1744 if !generics.span.is_empty() {
1747 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1748 }
1749
1750 let ty = match (
1753 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1754 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)),
1755 ) {
1756 (true, false) => self.parse_ty()?,
1757 (colon, _) => self.recover_missing_global_item_type(colon, None),
1759 };
1760
1761 let before_where_clause =
1764 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1765
1766 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 };
1767
1768 let after_where_clause = self.parse_where_clause()?;
1769
1770 if before_where_clause.has_where_token
1774 && let Some(rhs) = &rhs
1775 {
1776 self.dcx().emit_err(diagnostics::WhereClauseBeforeConstBody {
1777 span: before_where_clause.span,
1778 name: ident.span,
1779 body: rhs.span,
1780 sugg: if !after_where_clause.has_where_token {
1781 self.psess.source_map().span_to_snippet(rhs.span).ok().map(|body_s| {
1782 diagnostics::WhereClauseBeforeConstBodySugg {
1783 left: before_where_clause.span.shrink_to_lo(),
1784 snippet: body_s,
1785 right: before_where_clause.span.shrink_to_hi().to(rhs.span),
1786 }
1787 })
1788 } else {
1789 None
1792 },
1793 });
1794 }
1795
1796 let mut predicates = before_where_clause.predicates;
1803 predicates.extend(after_where_clause.predicates);
1804 let where_clause = WhereClause {
1805 has_where_token: before_where_clause.has_where_token
1806 || after_where_clause.has_where_token,
1807 predicates,
1808 span: if after_where_clause.has_where_token {
1809 after_where_clause.span
1810 } else {
1811 before_where_clause.span
1812 },
1813 };
1814
1815 if where_clause.has_where_token {
1816 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1817 }
1818
1819 generics.where_clause = where_clause;
1820
1821 if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
1822 return Ok((ident, generics, ty, Some(rhs)));
1823 }
1824 self.expect_semi()?;
1825
1826 Ok((ident, generics, ty, rhs))
1827 }
1828
1829 fn recover_missing_global_item_type(
1832 &mut self,
1833 colon_present: bool,
1834 m: Option<Mutability>,
1835 ) -> Box<Ty> {
1836 let kind = match m {
1839 Some(Mutability::Mut) => "static mut",
1840 Some(Mutability::Not) => "static",
1841 None => "const",
1842 };
1843
1844 let colon = match colon_present {
1845 true => "",
1846 false => ":",
1847 };
1848
1849 let span = self.prev_token.span.shrink_to_hi();
1850 let err = self.dcx().create_err(diagnostics::MissingConstType { span, colon, kind });
1851 err.stash(span, StashKey::ItemNoType);
1852
1853 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID })
1856 }
1857
1858 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1860 if self.token.is_keyword(kw::Struct) {
1861 let span = self.prev_token.span.to(self.token.span);
1862 let err = diagnostics::EnumStructMutuallyExclusive { span };
1863 if self.look_ahead(1, |t| t.is_ident()) {
1864 self.bump();
1865 self.dcx().emit_err(err);
1866 } else {
1867 return Err(self.dcx().create_err(err));
1868 }
1869 }
1870
1871 let prev_span = self.prev_token.span;
1872 let ident = self.parse_ident()?;
1873 let mut generics = self.parse_generics()?;
1874 generics.where_clause = self.parse_where_clause()?;
1875
1876 let (variants, _) = if self.token == TokenKind::Semi {
1878 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
1879 self.bump();
1880 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1881 } else {
1882 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| {
1883 p.parse_enum_variant(ident.span)
1884 })
1885 .map_err(|mut err| {
1886 err.span_label(ident.span, "while parsing this enum");
1887 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1889 let snapshot = self.create_snapshot_for_diagnostic();
1890 self.bump();
1891 match self.parse_ty() {
1892 Ok(_) => {
1893 err.span_suggestion_verbose(
1894 prev_span,
1895 "perhaps you meant to use `struct` here",
1896 "struct",
1897 Applicability::MaybeIncorrect,
1898 );
1899 }
1900 Err(e) => {
1901 e.cancel();
1902 }
1903 }
1904 self.restore_snapshot(snapshot);
1905 }
1906 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1907 self.bump(); err
1909 })?
1910 };
1911
1912 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1913 Ok(ItemKind::Enum(ident, generics, enum_definition))
1914 }
1915
1916 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1917 self.recover_vcs_conflict_marker();
1918 let variant_attrs = self.parse_outer_attributes()?;
1919 self.recover_vcs_conflict_marker();
1920 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1921 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1922 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1923 let vlo = this.token.span;
1924
1925 let vis = this.parse_visibility(FollowedByType::No)?;
1926 if !this.recover_nested_adt_item(kw::Enum)? {
1927 return Ok((None, Trailing::No, UsePreAttrPos::No));
1928 }
1929 let ident = this.parse_field_ident("enum", vlo)?;
1930
1931 if this.token == token::Bang {
1932 if let Err(err) = this.unexpected() {
1933 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();
1934 }
1935
1936 this.bump();
1937 this.parse_delim_args()?;
1938
1939 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1940 }
1941
1942 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)) {
1943 let (fields, recovered) =
1945 match this.parse_record_struct_body("struct", ident.span, false) {
1946 Ok((fields, recovered)) => (fields, recovered),
1947 Err(mut err) => {
1948 if this.token == token::Colon {
1949 return Err(err);
1951 }
1952 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1953 this.bump(); err.span_label(span, "while parsing this enum");
1955 err.help(help);
1956 let guar = err.emit_err();
1957 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1958 }
1959 };
1960 VariantData::Struct { fields, recovered }
1961 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1962 let body = match this.parse_tuple_struct_body() {
1963 Ok(body) => body,
1964 Err(mut err) => {
1965 if this.token == token::Colon {
1966 return Err(err);
1968 }
1969 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
1970 this.bump(); err.span_label(span, "while parsing this enum");
1972 err.help(help);
1973 err.emit();
1974 ::thin_vec::ThinVec::new()thin_vec![]
1975 }
1976 };
1977 VariantData::Tuple(body, DUMMY_NODE_ID)
1978 } else {
1979 VariantData::Unit(DUMMY_NODE_ID)
1980 };
1981
1982 let disr_expr =
1983 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 };
1984
1985 let span = vlo.to(this.prev_token.span);
1986 if ident.name == kw::Underscore {
1987 this.psess.gated_spans.gate(sym::unnamed_enum_variants, span);
1988 }
1989 let vr = ast::Variant {
1990 ident,
1991 vis,
1992 id: DUMMY_NODE_ID,
1993 attrs: variant_attrs,
1994 data: struct_def,
1995 disr_expr,
1996 span,
1997 is_placeholder: false,
1998 };
1999
2000 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
2001 })
2002 .map_err(|mut err| {
2003 err.help(help);
2004 err
2005 })
2006 }
2007
2008 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
2010 let ident = self.parse_ident()?;
2011
2012 let mut generics = self.parse_generics()?;
2013
2014 let vdata = if self.token.is_keyword(kw::Where) {
2029 let tuple_struct_body;
2030 (generics.where_clause, tuple_struct_body) =
2031 self.parse_struct_where_clause(ident, generics.span)?;
2032
2033 if let Some(body) = tuple_struct_body {
2034 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
2036 self.expect_semi()?;
2037 body
2038 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
2039 VariantData::Unit(DUMMY_NODE_ID)
2041 } else {
2042 let (fields, recovered) = self.parse_record_struct_body(
2044 "struct",
2045 ident.span,
2046 generics.where_clause.has_where_token,
2047 )?;
2048 VariantData::Struct { fields, recovered }
2049 }
2050 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
2052 VariantData::Unit(DUMMY_NODE_ID)
2053 } else if self.token == token::OpenBrace {
2055 let (fields, recovered) = self.parse_record_struct_body(
2056 "struct",
2057 ident.span,
2058 generics.where_clause.has_where_token,
2059 )?;
2060 VariantData::Struct { fields, recovered }
2061 } else if self.token == token::OpenParen {
2063 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
2064 generics.where_clause = self.parse_where_clause()?;
2065 self.expect_semi()?;
2066 body
2067 } else {
2068 let err = diagnostics::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
2069 return Err(self.dcx().create_err(err));
2070 };
2071
2072 Ok(ItemKind::Struct(ident, generics, vdata))
2073 }
2074
2075 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
2077 let ident = self.parse_ident()?;
2078
2079 let mut generics = self.parse_generics()?;
2080
2081 let vdata = if self.token.is_keyword(kw::Where) {
2082 generics.where_clause = self.parse_where_clause()?;
2083 let (fields, recovered) = self.parse_record_struct_body(
2084 "union",
2085 ident.span,
2086 generics.where_clause.has_where_token,
2087 )?;
2088 VariantData::Struct { fields, recovered }
2089 } else if self.token == token::OpenBrace {
2090 let (fields, recovered) = self.parse_record_struct_body(
2091 "union",
2092 ident.span,
2093 generics.where_clause.has_where_token,
2094 )?;
2095 VariantData::Struct { fields, recovered }
2096 } else {
2097 let token_str = super::token_descr(&self.token);
2098 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}");
2099 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2100 err.span_label(self.token.span, "expected `where` or `{` after union name");
2101 return Err(err);
2102 };
2103
2104 Ok(ItemKind::Union(ident, generics, vdata))
2105 }
2106
2107 pub(crate) fn parse_record_struct_body(
2112 &mut self,
2113 adt_ty: &str,
2114 ident_span: Span,
2115 parsed_where: bool,
2116 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
2117 let mut fields = ThinVec::new();
2118 let mut recovered = Recovered::No;
2119 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2120 while self.token != token::CloseBrace {
2121 match self.parse_field_def(adt_ty, ident_span) {
2122 Ok(field) => {
2123 fields.push(field);
2124 }
2125 Err(mut err) => {
2126 self.consume_block(
2127 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
2128 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
2129 ConsumeClosingDelim::No,
2130 );
2131 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}"));
2132 let guar = err.emit_err();
2133 recovered = Recovered::Yes(guar);
2134 break;
2135 }
2136 }
2137 }
2138 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
2139 } else {
2140 let token_str = super::token_descr(&self.token);
2141 let where_str = if parsed_where { "" } else { "`where`, or " };
2142 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}");
2143 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2144 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",));
2145 return Err(err);
2146 }
2147
2148 Ok((fields, recovered))
2149 }
2150
2151 fn parse_unsafe_field(&mut self) -> Safety {
2152 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)) {
2154 let span = self.prev_token.span;
2155 self.psess.gated_spans.gate(sym::unsafe_fields, span);
2156 Safety::Unsafe(span)
2157 } else {
2158 Safety::Default
2159 }
2160 }
2161 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
2164 let openparen_span = self.token.span;
2165 let mut encountered_colon = false;
2166 self.parse_paren_comma_seq(|p| {
2167 let attrs = p.parse_outer_attributes()?;
2168 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
2169 let mut snapshot = None;
2170 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
2171 snapshot = Some(p.create_snapshot_for_diagnostic());
2175 }
2176 let lo = p.token.span;
2177 let vis = match p.parse_visibility(FollowedByType::Yes) {
2178 Ok(vis) => vis,
2179 Err(err) => {
2180 if let Some(ref mut snapshot) = snapshot {
2181 snapshot.recover_vcs_conflict_marker();
2182 }
2183 return Err(err);
2184 }
2185 };
2186 let mut_restriction = p.parse_mut_restriction()?;
2187 encountered_colon |=
2188 p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
2189 let ty = match p.parse_ty() {
2192 Ok(ty) => ty,
2193 Err(err) => {
2194 if let Some(ref mut snapshot) = snapshot {
2195 snapshot.recover_vcs_conflict_marker();
2196 }
2197 return Err(err);
2198 }
2199 };
2200 let mut default = None;
2201 if p.token == token::Eq {
2202 let mut snapshot = p.create_snapshot_for_diagnostic();
2203 snapshot.bump();
2204 match snapshot.parse_expr_anon_const() {
2205 Ok(const_expr) => {
2206 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2207 p.psess.gated_spans.gate(sym::default_field_values, sp);
2208 p.restore_snapshot(snapshot);
2209 default = Some(const_expr);
2210 }
2211 Err(err) => {
2212 err.cancel();
2213 }
2214 }
2215 }
2216
2217 Ok((
2218 FieldDef {
2219 span: lo.to(ty.span),
2220 vis,
2221 extras: Self::field_def_extras(Safety::Default, mut_restriction, default),
2222 ident: None,
2223 id: DUMMY_NODE_ID,
2224 ty,
2225 attrs,
2226 is_placeholder: false,
2227 },
2228 Trailing::from(p.token == token::Comma),
2229 UsePreAttrPos::No,
2230 ))
2231 })
2232 })
2233 .map(|(r, _)| r)
2234 .map_err(|mut error| {
2235 if self.token == token::Colon {
2236 error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
2237 }
2238 if encountered_colon {
2239 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
2240 self.bump();
2241 error.subdiagnostic(UseRegularStructSuggestion {
2242 open: openparen_span,
2243 close: self.prev_token.span,
2244 semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
2245 });
2246 }
2247 error
2248 })
2249 }
2250
2251 fn field_def_extras(
2252 safety: Safety,
2253 mut_restriction: MutRestriction,
2254 default: Option<AnonConst>,
2255 ) -> Option<Box<FieldDefExtras>> {
2256 match (safety, mut_restriction, default) {
2257 (
2258 Safety::Default,
2259 MutRestriction { kind: RestrictionKind::Unrestricted, span: _ },
2262 None,
2263 ) => None,
2264 (safety, mut_restriction, default) => {
2265 Some(Box::new(FieldDefExtras { safety, mut_restriction, default }))
2266 }
2267 }
2268 }
2269
2270 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2272 self.recover_vcs_conflict_marker();
2273 let attrs = self.parse_outer_attributes()?;
2274 self.recover_vcs_conflict_marker();
2275 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2276 let lo = this.token.span;
2277 let vis = this.parse_visibility(FollowedByType::No)?;
2278 let mut_restriction = this.parse_mut_restriction()?;
2279 let safety = this.parse_unsafe_field();
2280 this.parse_single_struct_field(
2281 adt_ty,
2282 lo,
2283 vis,
2284 mut_restriction,
2285 safety,
2286 attrs,
2287 ident_span,
2288 )
2289 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2290 })
2291 }
2292
2293 fn parse_single_struct_field(
2295 &mut self,
2296 adt_ty: &str,
2297 lo: Span,
2298 vis: Visibility,
2299 mut_restriction: MutRestriction,
2300 safety: Safety,
2301 attrs: AttrVec,
2302 ident_span: Span,
2303 ) -> PResult<'a, FieldDef> {
2304 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, mut_restriction, safety, attrs)?;
2305 match self.token.kind {
2306 token::Comma => {
2307 self.bump();
2308 }
2309 token::Semi => {
2310 self.bump();
2311 let sp = self.prev_token.span;
2312 let mut err =
2313 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 `,`"));
2314 err.span_suggestion_short(
2315 sp,
2316 "replace `;` with `,`",
2317 ",",
2318 Applicability::MachineApplicable,
2319 );
2320 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}"));
2321 err.emit();
2322 }
2323 token::CloseBrace => {}
2324 token::DocComment(..) => {
2325 let previous_span = self.prev_token.span;
2326 let mut err = diagnostics::DocCommentDoesNotDocumentAnything {
2327 span: self.token.span,
2328 missing_comma: None,
2329 };
2330 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 {
2332 self.dcx().emit_err(err);
2333 } else {
2334 let sp = previous_span.shrink_to_hi();
2335 err.missing_comma = Some(sp);
2336 return Err(self.dcx().create_err(err));
2337 }
2338 }
2339 _ => {
2340 let sp = self.prev_token.span.shrink_to_hi();
2341 let msg =
2342 ::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));
2343
2344 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2346 && let Some(last_segment) = segments.last()
2347 {
2348 let guar = self.check_trailing_angle_brackets(
2349 last_segment,
2350 &[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)],
2351 );
2352 if let Some(_guar) = guar {
2353 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2356
2357 return Ok(a_var);
2360 }
2361 }
2362
2363 let mut err = self.dcx().struct_span_err(sp, msg);
2364
2365 if self.token.is_ident()
2366 || (self.token == TokenKind::Pound
2367 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2368 {
2369 err.span_suggestion(
2372 sp,
2373 "try adding a comma",
2374 ",",
2375 Applicability::MachineApplicable,
2376 );
2377 err.emit();
2378 } else {
2379 return Err(err);
2380 }
2381 }
2382 }
2383 Ok(a_var)
2384 }
2385
2386 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2387 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)) {
2388 let sm = self.psess.source_map();
2389 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2390 let semi_typo = self.token == token::Semi
2391 && self.look_ahead(1, |t| {
2392 t.is_path_start()
2393 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2396 (Ok(l), Ok(r)) => l.line == r.line,
2397 _ => true,
2398 }
2399 });
2400 if eq_typo || semi_typo {
2401 self.bump();
2402 err.with_span_suggestion_short(
2404 self.prev_token.span,
2405 "field names and their types are separated with `:`",
2406 ":",
2407 Applicability::MachineApplicable,
2408 )
2409 .emit();
2410 } else {
2411 return Err(err);
2412 }
2413 }
2414 Ok(())
2415 }
2416
2417 fn parse_name_and_ty(
2419 &mut self,
2420 adt_ty: &str,
2421 lo: Span,
2422 vis: Visibility,
2423 mut_restriction: MutRestriction,
2424 safety: Safety,
2425 attrs: AttrVec,
2426 ) -> PResult<'a, FieldDef> {
2427 let name = self.parse_field_ident(adt_ty, lo)?;
2428 if self.token == token::Bang {
2429 if let Err(mut err) = self.unexpected() {
2430 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2432 return Err(err);
2433 }
2434 }
2435 self.expect_field_ty_separator()?;
2436 let ty = self.parse_ty()?;
2437 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2438 return Err(self
2439 .dcx()
2440 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2441 .with_span_suggestion_verbose(
2442 self.token.span,
2443 "write a path separator here",
2444 "::",
2445 Applicability::MaybeIncorrect,
2446 ));
2447 }
2448 let default = if self.token == token::Eq {
2449 self.bump();
2450 let const_expr = self.parse_expr_anon_const()?;
2451 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2452 self.psess.gated_spans.gate(sym::default_field_values, sp);
2453 Some(const_expr)
2454 } else {
2455 None
2456 };
2457 Ok(FieldDef {
2458 span: lo.to(self.prev_token.span),
2459 ident: Some(name),
2460 vis,
2461 extras: Self::field_def_extras(safety, mut_restriction, default),
2462 id: DUMMY_NODE_ID,
2463 ty,
2464 attrs,
2465 is_placeholder: false,
2466 })
2467 }
2468
2469 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2472 let (ident, kind) = self.ident_or_err(true)?;
2473 if kind == IdentKind::Normal
2474 && ident.is_reserved()
2475 && !(ident.name == kw::Underscore && adt_ty == "enum")
2476 {
2477 let snapshot = self.create_snapshot_for_diagnostic();
2478 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2479 let inherited_vis = Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited };
2480 let fn_parse_mode =
2482 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2483 match self.parse_fn(
2484 &mut AttrVec::new(),
2485 fn_parse_mode,
2486 lo,
2487 &inherited_vis,
2488 Case::Insensitive,
2489 ) {
2490 Ok(_) => self
2491 .dcx()
2492 .struct_span_err(
2493 lo.to(self.prev_token.span),
2494 ::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"),
2495 )
2496 .with_help(
2497 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2498 )
2499 .with_help(
2500 "see https://doc.rust-lang.org/book/ch05-03-method-syntax.html \
2501 for more information",
2502 ),
2503 Err(err) => {
2504 err.cancel();
2505 self.restore_snapshot(snapshot);
2506 self.expected_ident_found_err()
2507 }
2508 }
2509 } 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)) {
2510 match self.parse_item_struct() {
2511 Ok(item) => {
2512 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2513 self.dcx()
2514 .struct_span_err(
2515 lo.with_hi(ident.span.hi()),
2516 ::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"),
2517 )
2518 .with_help(
2519 "consider creating a new `struct` definition instead of nesting",
2520 )
2521 }
2522 Err(err) => {
2523 err.cancel();
2524 self.restore_snapshot(snapshot);
2525 self.expected_ident_found_err()
2526 }
2527 }
2528 } else {
2529 let mut err = self.expected_ident_found_err();
2530 if self.eat_keyword_noexpect(kw::Let)
2531 && let removal_span = self.prev_token.span.until(self.token.span)
2532 && let Ok(ident) = self
2533 .parse_ident_common(false)
2534 .map_err(|err| err.cancel())
2536 && self.token == TokenKind::Colon
2537 {
2538 err.span_suggestion_verbose(
2539 removal_span,
2540 "remove the `let` keyword",
2541 String::new(),
2542 Applicability::MachineApplicable,
2543 );
2544 err.note("the `let` keyword is not allowed in `struct` fields");
2545 err.note(
2546 "see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> \
2547 for more information",
2548 );
2549 err.emit();
2550 return Ok(ident);
2551 } else {
2552 self.restore_snapshot(snapshot);
2553 }
2554 err
2555 };
2556 return Err(err);
2557 }
2558 self.bump();
2559 Ok(ident)
2560 }
2561
2562 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2570 let ident = self.parse_ident()?;
2571 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)) {
2572 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)) {
2574 let params = self.parse_token_tree(); let pspan = params.span();
2576 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2577 self.unexpected()?;
2578 }
2579 let body = self.parse_token_tree(); let bspan = body.span();
2582 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]);
2584 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2585 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2586 } else {
2587 self.unexpected_any()?
2588 };
2589
2590 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2591 Ok(ItemKind::MacroDef(
2592 ident,
2593 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2594 ))
2595 }
2596
2597 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2599 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)) {
2600 let macro_rules_span = self.token.span;
2601
2602 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2603 return IsMacroRulesItem::Yes { has_bang: true };
2604 } else if self.look_ahead(1, |t| t.is_ident()) {
2605 self.dcx().emit_err(diagnostics::MacroRulesMissingBang {
2607 span: macro_rules_span,
2608 hi: macro_rules_span.shrink_to_hi(),
2609 });
2610
2611 return IsMacroRulesItem::Yes { has_bang: false };
2612 }
2613 }
2614
2615 IsMacroRulesItem::No
2616 }
2617
2618 fn parse_item_macro_rules(
2620 &mut self,
2621 vis: &Visibility,
2622 has_bang: bool,
2623 ) -> PResult<'a, ItemKind> {
2624 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 {
2627 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2629 let ident = self.parse_ident()?;
2630
2631 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2632 let span = self.prev_token.span;
2634 self.dcx().emit_err(diagnostics::MacroNameRemoveBang { span });
2635 }
2636
2637 let body = self.parse_delim_args()?;
2638 self.eat_semi_for_macro_if_needed(&body, None);
2639 self.complain_if_pub_macro(vis, true);
2640
2641 Ok(ItemKind::MacroDef(
2642 ident,
2643 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2644 ))
2645 }
2646
2647 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2650 if let VisibilityKind::Inherited = vis.kind {
2651 return;
2652 }
2653
2654 let vstr = pprust::vis_to_string(vis);
2655 let vstr = vstr.trim_end();
2656 if macro_rules {
2657 self.dcx().emit_err(diagnostics::MacroRulesVisibility { span: vis.span, vis: vstr });
2658 } else {
2659 self.dcx()
2660 .emit_err(diagnostics::MacroInvocationVisibility { span: vis.span, vis: vstr });
2661 }
2662 }
2663
2664 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
2665 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)) {
2666 self.report_invalid_macro_expansion_item(args, path);
2667 }
2668 }
2669
2670 pub fn parse_test_binder_constraints(&mut self) -> PResult<'a, Box<TestBinderConstraints>> {
2672 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
2673 let mut generics = self.parse_generics()?;
2674 generics.where_clause = self.parse_where_clause()?;
2675 let body = self.parse_test_binder_body()?;
2676 Ok(Box::new(TestBinderConstraints { generics, body: Box::new(body) }))
2677 }
2678
2679 pub fn parse_test_binder_body(&mut self) -> PResult<'a, TestBinderBody> {
2680 let mut foralls = ThinVec::new();
2681 let mut exists = ThinVec::new();
2682 let mut constraints = Vec::new();
2683 let mut predicates = Vec::new();
2684 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| {
2685 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)) {
2686 predicates.push(this.parse_where_clause()?);
2687 return Ok(());
2688 }
2689 match this.token.ident() {
2690 Some((Ident { name: sym::forall, .. }, IdentKind::Normal)) => {
2691 foralls.push(this.parse_test_binder_forall()?)
2692 }
2693 Some((Ident { name: sym::exists, .. }, IdentKind::Normal)) => {
2694 exists.push(this.parse_test_binder_exists()?)
2695 }
2696
2697 _ => constraints.push(this.parse_test_binder_constraint()?),
2698 }
2699 Ok(())
2700 })?;
2701 Ok(TestBinderBody { foralls, exists, constraints, predicates })
2702 }
2703
2704 pub fn parse_test_binder_forall(&mut self) -> PResult<'a, TestBinderForall> {
2705 let span = self.token.span;
2706 self.bump();
2707
2708 let mut generics = self.parse_generics()?;
2709 generics.where_clause = self.parse_where_clause()?;
2710
2711 let body = self.parse_test_binder_body()?;
2712
2713 let assert_on_exit = if let Some((i, IdentKind::Normal)) = self.token.ident()
2714 && i.name == sym::expect
2715 {
2716 self.bump();
2717 let items = self
2718 .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| {
2719 this.parse_test_binder_constraint()
2720 })?
2721 .0;
2722 Some(items)
2723 } else {
2724 None
2725 };
2726
2727 Ok(TestBinderForall { span, node_id: DUMMY_NODE_ID, generics, body, assert_on_exit })
2728 }
2729
2730 pub fn parse_test_binder_exists(&mut self) -> PResult<'a, TestBinderExists> {
2731 let span = self.token.span;
2732 self.bump();
2733 let params = self.parse_generics()?.params;
2734 let body = self.parse_test_binder_body()?;
2735 Ok(TestBinderExists { span, node_id: DUMMY_NODE_ID, params, body })
2736 }
2737
2738 pub fn parse_test_binder_constraint(&mut self) -> PResult<'a, TestBinderConstraint> {
2739 match self.token.ident() {
2740 Some((Ident { name: sym::and, .. }, IdentKind::Normal)) => {
2741 self.bump();
2742 let items = self
2743 .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| {
2744 this.parse_test_binder_constraint()
2745 })?
2746 .0;
2747 Ok(TestBinderConstraint::And { items })
2748 }
2749 Some((Ident { name: sym::or, .. }, IdentKind::Normal)) => {
2750 self.bump();
2751 let items = self
2752 .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| {
2753 this.parse_test_binder_constraint()
2754 })?
2755 .0;
2756 Ok(TestBinderConstraint::Or { items })
2757 }
2758 _ 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)) => {
2759 let bound_type_constraint = self.parse_test_binder_bound_type_constraint()?;
2760 Ok(TestBinderConstraint::AliasOutlives { bound_type_constraint })
2761 }
2762 _ if self.token.lifetime().is_some() => {
2763 let lhs = self.expect_lifetime();
2764 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon))?;
2765 if !self.check_lifetime() {
2766 self.unexpected()?;
2767 }
2768 let rhs = self.expect_lifetime();
2769 Ok(TestBinderConstraint::Lifetime { lhs, rhs })
2770 }
2771 _ if self.token.can_begin_type() => {
2772 let lhs = self.parse_ty_for_where_clause()?;
2773 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon))?;
2774 if !self.check_lifetime() {
2775 self.unexpected()?;
2776 }
2777 let rhs = self.expect_lifetime();
2778 Ok(TestBinderConstraint::PlaceholderOutlives { lhs, rhs })
2779 }
2780 _ => Err(self.dcx().struct_span_err(self.token.span, "unexpected token")),
2781 }
2782 }
2783
2784 fn parse_test_binder_bound_type_constraint(
2785 &mut self,
2786 ) -> PResult<'a, TestBinderBoundTypeConstraint> {
2787 let lo = self.token.span;
2788 let ast::WhereBoundPredicate { bound_generic_params, bounded_ty, bounds } =
2789 self.parse_ty_where_predicate_kind()?;
2790 let mut rhs = None;
2791 for bound in bounds {
2792 match bound {
2793 GenericBound::Trait(poly_trait_ref) => {
2794 self.dcx().span_err(poly_trait_ref.span, "trait bounds aren't supported here");
2795 }
2796 GenericBound::Use(_, span) => {
2797 self.dcx().span_err(span, "use bounds aren't supported here");
2798 }
2799 GenericBound::Outlives(lifetime) => {
2800 if rhs.is_some() {
2801 self.dcx().span_err(
2802 lifetime.ident.span,
2803 "only one lifetime on the rhs supported",
2804 );
2805 } else {
2806 rhs = Some(lifetime);
2807 }
2808 }
2809 }
2810 }
2811 match rhs {
2812 Some(rhs) => Ok(TestBinderBoundTypeConstraint {
2813 span: lo.to(self.prev_token.span),
2814 node_id: DUMMY_NODE_ID,
2815 params: bound_generic_params,
2816 lhs: bounded_ty,
2817 rhs,
2818 }),
2819 None => Err(self.dcx().struct_span_err(
2820 bounded_ty.span,
2821 "expected a single lifetime on the rhs of this constraint",
2822 )),
2823 }
2824 }
2825
2826 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
2827 let span = args.dspan.entire();
2828 let mut err = self.dcx().struct_span_err(
2829 span,
2830 "macros that expand to items must be delimited with braces or followed by a semicolon",
2831 );
2832 if !span.from_expansion() {
2835 let DelimSpan { open, close } = args.dspan;
2836 if let Some(path) = path
2839 && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2840 && args.delim == Delimiter::Parenthesis
2841 {
2842 let replace =
2843 if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2844 err.multipart_suggestion(
2845 "to define a macro, remove the parentheses around the macro name",
2846 ::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())],
2847 Applicability::MachineApplicable,
2848 );
2849 } else {
2850 err.multipart_suggestion(
2851 "change the delimiters to curly braces",
2852 ::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())],
2853 Applicability::MaybeIncorrect,
2854 );
2855 err.span_suggestion_verbose(
2856 span.with_neighbor(self.token.span).shrink_to_hi(),
2857 "add a semicolon",
2858 ';',
2859 Applicability::MaybeIncorrect,
2860 );
2861 }
2862 }
2863 err.emit();
2864 }
2865
2866 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2869 if (self.token.is_keyword(kw::Enum)
2870 || self.token.is_keyword(kw::Struct)
2871 || self.token.is_keyword(kw::Union))
2872 && self.look_ahead(1, |t| t.is_ident())
2873 {
2874 let kw_token = self.token;
2875 let kw_str = pprust::token_to_string(&kw_token);
2876 let item = self.parse_item(
2877 ForceCollect::No,
2878 AllowConstBlockItems::DoesNotMatter, )?;
2880 let mut item = item.unwrap().span;
2881 if self.token == token::Comma {
2882 item = item.to(self.token.span);
2883 }
2884 self.dcx().emit_err(diagnostics::NestedAdt {
2885 span: kw_token.span,
2886 item,
2887 kw_str,
2888 keyword: keyword.as_str(),
2889 });
2890 return Ok(false);
2892 }
2893 Ok(true)
2894 }
2895
2896 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2897 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2898 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)) {
2901 return true;
2902 }
2903 let mut i = 0;
2904 while i < ALL_QUALS.len() {
2905 let action = self.look_ahead(i + look_ahead, |token| {
2906 if token.is_keyword(kw::Impl) {
2907 return Some(true);
2908 }
2909 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2910 return None;
2912 }
2913 Some(false)
2914 });
2915 if let Some(ret) = action {
2916 return ret;
2917 }
2918 i += 1;
2919 }
2920
2921 self.is_keyword_ahead(i, &[kw::Impl])
2922 }
2923
2924 fn try_recover_const_missing_semi(
2932 &mut self,
2933 rhs: &Option<Box<Expr>>,
2934 const_span: Span,
2935 ) -> Option<Box<Expr>> {
2936 if self.token == TokenKind::Semi {
2937 return None;
2938 }
2939 let Some(rhs) = rhs else {
2940 return None;
2941 };
2942 if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
2943 return None;
2944 }
2945 if let Some((span, guar)) =
2946 self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
2947 {
2948 self.fn_body_missing_semi_guar = Some(guar);
2949 Some(self.mk_expr(span, ExprKind::Err(guar)))
2950 } else {
2951 None
2952 }
2953 }
2954}
2955
2956enum IsMacroRulesItem {
2957 Yes { has_bang: bool },
2958 No,
2959}
2960
2961struct UsePathList<'a> {
2962 elements: &'a [ast::PathSegment],
2963 prev: Option<&'a Self>,
2964}