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