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