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, InvisibleOrigin, 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_session::lint::builtin::VARARGS_WITHOUT_PATTERN;
14use rustc_span::edit_distance::edit_distance;
15use rustc_span::edition::Edition;
16use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, respan, sym};
17use thin_vec::{ThinVec, thin_vec};
18use tracing::debug;
19
20use super::diagnostics::{ConsumeClosingDelim, dummy_arg};
21use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
22use super::{
23 AllowConstBlockItems, AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect,
24 Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,
25};
26use crate::errors::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField};
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 mut err = this
196 .dcx()
197 .create_err(errors::VisibilityNotFollowedByItem { span: vis.span, vis });
198 if let Some((ident, _)) = this.token.ident()
199 && !ident.is_used_keyword()
200 && let Some((similar_kw, is_incorrect_case)) = ident
201 .name
202 .find_similar(&rustc_span::symbol::used_keywords(|| ident.span.edition()))
203 {
204 err.subdiagnostic(errors::MisspelledKw {
205 similar_kw: similar_kw.to_string(),
206 span: ident.span,
207 is_incorrect_case,
208 });
209 }
210 err.emit();
211 }
212
213 if let Defaultness::Default(span) = def {
214 this.dcx().emit_err(errors::DefaultNotFollowedByItem { span });
215 } else if let Defaultness::Final(span) = def {
216 this.dcx().emit_err(errors::FinalNotFollowedByItem { span });
217 }
218
219 if !attrs_allowed {
220 this.recover_attrs_no_item(&attrs)?;
221 }
222 Ok((None, Trailing::No, UsePreAttrPos::No))
223 })
224 }
225
226 fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
228 match def {
229 Defaultness::Default(span) => {
230 self.dcx().emit_err(errors::InappropriateDefault {
231 span,
232 article: kind.article(),
233 descr: kind.descr(),
234 });
235 }
236 Defaultness::Final(span) => {
237 self.dcx().emit_err(errors::InappropriateFinal {
238 span,
239 article: kind.article(),
240 descr: kind.descr(),
241 });
242 }
243 Defaultness::Implicit => (),
244 }
245 }
246
247 fn parse_item_kind(
249 &mut self,
250 attrs: &mut AttrVec,
251 macros_allowed: bool,
252 allow_const_block_items: AllowConstBlockItems,
253 lo: Span,
254 vis: &Visibility,
255 def: &mut Defaultness,
256 fn_parse_mode: FnParseMode,
257 case: Case,
258 ) -> PResult<'a, Option<ItemKind>> {
259 let check_pub = def == &Defaultness::Implicit;
260 let mut def_ = || mem::replace(def, Defaultness::Implicit);
261
262 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) {
263 self.parse_use_item()?
264 } else if self.check_fn_front_matter(check_pub, case) {
265 let defaultness = def_();
267 if let Defaultness::Default(span) = defaultness {
268 self.psess.gated_spans.gate(sym::min_specialization, span);
272 self.psess.gated_spans.ungate_last(sym::specialization, span);
273 }
274 let (ident, sig, generics, contract, body) =
275 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
276 ItemKind::Fn(Box::new(Fn {
277 defaultness,
278 ident,
279 sig,
280 generics,
281 contract,
282 body,
283 define_opaque: None,
284 eii_impls: ThinVec::new(),
285 }))
286 } 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) {
287 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) {
288 self.parse_item_extern_crate()?
290 } else {
291 self.parse_item_foreign_mod(attrs, Safety::Default)?
293 }
294 } else if self.is_unsafe_foreign_mod() {
295 let safety = self.parse_safety(Case::Sensitive);
297 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern))?;
298 self.parse_item_foreign_mod(attrs, safety)?
299 } else if let Some(safety) = self.parse_global_static_front_matter(case) {
300 let mutability = self.parse_mutability();
302 self.parse_static_item(safety, mutability)?
303 } 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() {
304 self.parse_item_trait(attrs, lo)?
306 } else if self.check_impl_frontmatter(0) {
307 self.parse_item_impl(attrs, def_(), false)?
309 } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
310 allow_const_block_items
311 && self.check_inline_const(0)
312 {
313 if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
315 {
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:315",
"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(315u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("Parsing a const block item that does not matter: {0:?}",
self.token.span) as &dyn Value))])
});
} else { ; }
};debug!("Parsing a const block item that does not matter: {:?}", self.token.span);
316 };
317 ItemKind::ConstBlock(self.parse_const_block_item()?)
318 } else if let Const::Yes(const_span) = self.parse_constness(case) {
319 self.recover_const_mut(const_span);
321 self.recover_missing_kw_before_item()?;
322 let (ident, generics, ty, rhs_kind) = self.parse_const_item(false, const_span)?;
323 ItemKind::Const(Box::new(ConstItem {
324 defaultness: def_(),
325 ident,
326 generics,
327 ty,
328 rhs_kind,
329 define_opaque: None,
330 }))
331 } else if let Some(kind) = self.is_reuse_item() {
332 self.parse_item_delegation(attrs, def_(), kind)?
333 } 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)
334 || 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])
335 {
336 self.parse_item_mod(attrs)?
338 } 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) {
339 if let Const::Yes(const_span) = self.parse_constness(case) {
340 self.recover_const_mut(const_span);
342 self.recover_missing_kw_before_item()?;
343 let (ident, generics, ty, rhs_kind) = self.parse_const_item(true, const_span)?;
344 self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span));
347 ItemKind::Const(Box::new(ConstItem {
348 defaultness: def_(),
349 ident,
350 generics,
351 ty,
352 rhs_kind,
353 define_opaque: None,
354 }))
355 } else {
356 self.parse_type_alias(def_())?
358 }
359 } 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) {
360 self.parse_item_enum()?
362 } 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) {
363 self.parse_item_struct()?
365 } else if self.is_kw_followed_by_ident(kw::Union) {
366 self.bump(); self.parse_item_union()?
369 } else if self.is_builtin() {
370 return self.parse_item_builtin();
372 } 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) {
373 self.parse_item_decl_macro(lo)?
375 } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
376 self.parse_item_macro_rules(vis, has_bang)?
378 } else if self.isnt_macro_invocation()
379 && (self.token.is_ident_named(sym::import)
380 || self.token.is_ident_named(sym::using)
381 || self.token.is_ident_named(sym::include)
382 || self.token.is_ident_named(sym::require))
383 {
384 return self.recover_import_as_use();
385 } else if self.isnt_macro_invocation() && vis.kind.is_pub() {
386 self.recover_missing_kw_before_item()?;
387 return Ok(None);
388 } else if self.isnt_macro_invocation() && case == Case::Sensitive {
389 _ = def_;
390
391 return self.parse_item_kind(
393 attrs,
394 macros_allowed,
395 allow_const_block_items,
396 lo,
397 vis,
398 def,
399 fn_parse_mode,
400 Case::Insensitive,
401 );
402 } else if macros_allowed && self.check_path() {
403 if self.isnt_macro_invocation() {
404 self.recover_missing_kw_before_item()?;
405 }
406 ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
408 } else {
409 return Ok(None);
410 };
411 Ok(Some(info))
412 }
413
414 fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
415 let span = self.token.span;
416 let token_name = super::token_descr(&self.token);
417 let snapshot = self.create_snapshot_for_diagnostic();
418 self.bump();
419 match self.parse_use_item() {
420 Ok(u) => {
421 self.dcx().emit_err(errors::RecoverImportAsUse { span, token_name });
422 Ok(Some(u))
423 }
424 Err(e) => {
425 e.cancel();
426 self.restore_snapshot(snapshot);
427 Ok(None)
428 }
429 }
430 }
431
432 fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
433 let tree = self.parse_use_tree()?;
434 if let Err(mut e) = self.expect_semi() {
435 match tree.kind {
436 UseTreeKind::Glob(_) => {
437 e.note("the wildcard token must be last on the path");
438 }
439 UseTreeKind::Nested { .. } => {
440 e.note("glob-like brace syntax must be last on the path");
441 }
442 _ => (),
443 }
444 return Err(e);
445 }
446 Ok(ItemKind::Use(tree))
447 }
448
449 pub(super) fn is_path_start_item(&mut self) -> bool {
451 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{..}) }
457
458 fn is_reuse_item(&mut self) -> Option<ReuseKind> {
459 if !self.token.is_keyword(kw::Reuse) {
460 return None;
461 }
462
463 if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
465 Some(ReuseKind::Path)
466 } else if self.check_impl_frontmatter(1) {
467 Some(ReuseKind::Impl)
468 } else {
469 None
470 }
471 }
472
473 fn isnt_macro_invocation(&mut self) -> bool {
475 self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
476 }
477
478 fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
481 let is_pub = self.prev_token.is_keyword(kw::Pub);
482 let is_const = self.prev_token.is_keyword(kw::Const);
483 let ident_span = self.token.span;
484 let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };
485 let insert_span = ident_span.shrink_to_lo();
486
487 let ident = if self.token.is_ident()
488 && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
489 && self.look_ahead(1, |t| {
490 #[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)
491 }) {
492 self.parse_ident_common(true).unwrap()
493 } else {
494 return Ok(());
495 };
496
497 let mut found_generics = false;
498 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Lt,
token_type: crate::parser::token_type::TokenType::Lt,
}exp!(Lt)) {
499 found_generics = true;
500 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Gt,
token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)]);
501 self.bump(); }
503
504 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)) {
505 if self.look_ahead(1, |t| *t == token::CloseBrace) {
507 Some(errors::MissingKeywordForItemDefinition::EnumOrStruct { span })
509 } else if self.look_ahead(2, |t| *t == token::Colon)
510 || self.look_ahead(3, |t| *t == token::Colon)
511 {
512 Some(errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident })
514 } else {
515 Some(errors::MissingKeywordForItemDefinition::Enum { span, insert_span, ident })
516 }
517 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
518 self.bump(); let is_method = self.recover_self_param();
521
522 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);
523
524 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)) {
525 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)]);
526 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);
528 if is_method {
529 errors::MissingKeywordForItemDefinition::Method { span, insert_span, ident }
530 } else {
531 errors::MissingKeywordForItemDefinition::Function { span, insert_span, ident }
532 }
533 } 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)) {
534 errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
535 } else {
536 errors::MissingKeywordForItemDefinition::Ambiguous {
537 span,
538 subdiag: if found_generics {
539 None
540 } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
541 Some(errors::AmbiguousMissingKwForItemSub::SuggestMacro {
542 span: ident_span,
543 snippet,
544 })
545 } else {
546 Some(errors::AmbiguousMissingKwForItemSub::HelpMacro)
547 },
548 }
549 };
550 Some(err)
551 } else if found_generics {
552 Some(errors::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
553 } else {
554 None
555 };
556
557 if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
558 }
559
560 fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
561 Ok(None)
563 }
564
565 fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
567 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() {
570 Ok(args) => {
572 self.eat_semi_for_macro_if_needed(&args, Some(&path));
573 self.complain_if_pub_macro(vis, false);
574 Ok(MacCall { path, args })
575 }
576
577 Err(mut err) => {
578 if self.token.is_ident()
580 && let [segment] = path.segments.as_slice()
581 && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
582 {
583 err.span_suggestion(
584 path.span,
585 "perhaps you meant to define a macro",
586 "macro_rules",
587 Applicability::MachineApplicable,
588 );
589 }
590 Err(err)
591 }
592 }
593 }
594
595 fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
597 let ([start @ end] | [start, .., end]) = attrs else {
598 return Ok(());
599 };
600 let msg = if end.is_doc_comment() {
601 "expected item after doc comment"
602 } else {
603 "expected item after attributes"
604 };
605 let mut err = self.dcx().struct_span_err(end.span, msg);
606 if end.is_doc_comment() {
607 err.span_label(end.span, "this doc comment doesn't document anything");
608 } else if self.token == TokenKind::Semi {
609 err.span_suggestion_verbose(
610 self.token.span,
611 "consider removing this semicolon",
612 "",
613 Applicability::MaybeIncorrect,
614 );
615 }
616 if let [.., penultimate, _] = attrs {
617 err.span_label(start.span.to(penultimate.span), "other attributes here");
618 }
619 Err(err)
620 }
621
622 fn is_async_fn(&self) -> bool {
623 self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
624 }
625
626 fn parse_polarity(&mut self) -> ast::ImplPolarity {
627 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()) {
629 self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
630 self.bump(); ast::ImplPolarity::Negative(self.prev_token.span)
632 } else {
633 ast::ImplPolarity::Positive
634 }
635 }
636
637 fn parse_item_impl(
652 &mut self,
653 attrs: &mut AttrVec,
654 defaultness: Defaultness,
655 is_reuse: bool,
656 ) -> PResult<'a, ItemKind> {
657 let mut constness = self.parse_constness(Case::Sensitive);
658 let safety = self.parse_safety(Case::Sensitive);
659 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
660
661 let mut generics = if self.choose_generics_over_qpath(0) {
663 self.parse_generics()?
664 } else {
665 let mut generics = Generics::default();
666 generics.span = self.prev_token.span.shrink_to_hi();
669 generics
670 };
671
672 if let Const::No = constness {
673 constness = self.parse_constness(Case::Sensitive);
675 }
676
677 if let Const::Yes(span) = constness {
678 self.psess.gated_spans.gate(sym::const_trait_impl, span);
679 }
680
681 if (self.token_uninterpolated_span().at_least_rust_2018()
683 && self.token.is_keyword(kw::Async))
684 || self.is_kw_followed_by_ident(kw::Async)
685 {
686 self.bump();
687 self.dcx().emit_err(errors::AsyncImpl { span: self.prev_token.span });
688 }
689
690 let polarity = self.parse_polarity();
691
692 let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
694 {
695 let span = self.prev_token.span.between(self.token.span);
696 return Err(self.dcx().create_err(errors::MissingTraitInTraitImpl {
697 span,
698 for_span: span.to(self.token.span),
699 }));
700 } else {
701 self.parse_ty_with_generics_recovery(&generics)?
702 };
703
704 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));
706 let missing_for_span = self.prev_token.span.between(self.token.span);
707
708 let ty_second = if self.token == token::DotDot {
709 self.bump(); Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
716 } else if has_for || self.token.can_begin_type() {
717 Some(self.parse_ty()?)
718 } else {
719 None
720 };
721
722 generics.where_clause = self.parse_where_clause()?;
723
724 let impl_items = if is_reuse {
725 Default::default()
726 } else {
727 self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
728 };
729
730 let (of_trait, self_ty) = match ty_second {
731 Some(ty_second) => {
732 if !has_for {
734 self.dcx().emit_err(errors::MissingForInTraitImpl { span: missing_for_span });
735 }
736
737 let ty_first = *ty_first;
738 let path = match ty_first.kind {
739 TyKind::Path(None, path) => path,
741 other => {
742 if let TyKind::ImplTrait(_, bounds) = other
743 && let [bound] = bounds.as_slice()
744 && let GenericBound::Trait(poly_trait_ref) = bound
745 {
746 let extra_impl_kw = ty_first.span.until(bound.span());
750 self.dcx().emit_err(errors::ExtraImplKeywordInTraitImpl {
751 extra_impl_kw,
752 impl_trait_span: ty_first.span,
753 });
754 poly_trait_ref.trait_ref.path.clone()
755 } else {
756 return Err(self.dcx().create_err(
757 errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span },
758 ));
759 }
760 }
761 };
762 let trait_ref = TraitRef { path, ref_id: ty_first.id };
763
764 let of_trait =
765 Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
766 (of_trait, ty_second)
767 }
768 None => {
769 let self_ty = ty_first;
770 let error = |modifier, modifier_name, modifier_span| {
771 self.dcx().create_err(errors::TraitImplModifierInInherentImpl {
772 span: self_ty.span,
773 modifier,
774 modifier_name,
775 modifier_span,
776 self_ty: self_ty.span,
777 })
778 };
779
780 if let Safety::Unsafe(span) = safety {
781 error("unsafe", "unsafe", span).with_code(E0197).emit();
782 }
783 if let ImplPolarity::Negative(span) = polarity {
784 error("!", "negative", span).emit();
785 }
786 if let Defaultness::Default(def_span) = defaultness {
787 error("default", "default", def_span).emit();
788 }
789 if let Const::Yes(span) = constness {
790 self.psess.gated_spans.gate(sym::const_trait_impl, span);
791 }
792 (None, self_ty)
793 }
794 };
795
796 Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
797 }
798
799 fn parse_item_delegation(
800 &mut self,
801 attrs: &mut AttrVec,
802 defaultness: Defaultness,
803 kind: ReuseKind,
804 ) -> PResult<'a, ItemKind> {
805 let span = self.token.span;
806 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Reuse,
token_type: crate::parser::token_type::TokenType::KwReuse,
}exp!(Reuse))?;
807
808 let item_kind = match kind {
809 ReuseKind::Path => self.parse_path_like_delegation(),
810 ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
811 }?;
812
813 self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
814
815 Ok(item_kind)
816 }
817
818 fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
819 Ok(if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
820 Some(self.parse_block()?)
821 } else {
822 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))?;
823 None
824 })
825 }
826
827 fn parse_impl_delegation(
828 &mut self,
829 span: Span,
830 attrs: &mut AttrVec,
831 defaultness: Defaultness,
832 ) -> PResult<'a, ItemKind> {
833 let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
834 let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
835
836 let until_expr_span = span.to(self.prev_token.span);
837
838 let Some(of_trait) = of_trait else {
839 return Err(self
840 .dcx()
841 .create_err(errors::ImplReuseInherentImpl { span: until_expr_span }));
842 };
843
844 let body = self.parse_delegation_body()?;
845 let whole_reuse_span = span.to(self.prev_token.span);
846
847 items.push(Box::new(AssocItem {
848 id: DUMMY_NODE_ID,
849 attrs: Default::default(),
850 span: whole_reuse_span,
851 tokens: None,
852 vis: Visibility {
853 kind: VisibilityKind::Inherited,
854 span: whole_reuse_span,
855 tokens: None,
856 },
857 kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
858 qself: None,
859 prefix: of_trait.trait_ref.path.clone(),
860 suffixes: DelegationSuffixes::Glob(whole_reuse_span),
861 body,
862 })),
863 }));
864
865 Ok(impl_item)
866 }
867
868 fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
869 let (qself, path) = if self.eat_lt() {
870 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
871 (Some(qself), path)
872 } else {
873 (None, self.parse_path(PathStyle::Expr)?)
874 };
875
876 let rename = |this: &mut Self| {
877 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 })
878 };
879
880 Ok(if self.eat_path_sep() {
881 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)) {
882 DelegationSuffixes::Glob(self.prev_token.span)
883 } else {
884 let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
885 DelegationSuffixes::List(
886 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,
887 )
888 };
889
890 ItemKind::DelegationMac(Box::new(DelegationMac {
891 qself,
892 prefix: path,
893 suffixes,
894 body: self.parse_delegation_body()?,
895 }))
896 } else {
897 let rename = rename(self)?;
898 let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
899
900 ItemKind::Delegation(Box::new(Delegation {
901 id: DUMMY_NODE_ID,
902 qself,
903 path,
904 ident,
905 rename,
906 body: self.parse_delegation_body()?,
907 from_glob: false,
908 }))
909 })
910 }
911
912 fn parse_item_list<T>(
913 &mut self,
914 attrs: &mut AttrVec,
915 mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
916 ) -> PResult<'a, ThinVec<T>> {
917 let open_brace_span = self.token.span;
918
919 if self.token == TokenKind::Semi {
921 self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
922 self.bump();
923 return Ok(ThinVec::new());
924 }
925
926 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
927 attrs.extend(self.parse_inner_attributes()?);
928
929 let mut items = ThinVec::new();
930 while !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)) {
931 if self.recover_doc_comment_before_brace() {
932 continue;
933 }
934 self.recover_vcs_conflict_marker();
935 match parse_item(self) {
936 Ok(None) => {
937 let mut is_unnecessary_semicolon = !items.is_empty()
938 && self
956 .span_to_snippet(self.prev_token.span)
957 .is_ok_and(|snippet| snippet == "}")
958 && self.token == token::Semi;
959 let mut semicolon_span = self.token.span;
960 if !is_unnecessary_semicolon {
961 is_unnecessary_semicolon =
963 self.token == token::OpenBrace && self.prev_token == token::Semi;
964 semicolon_span = self.prev_token.span;
965 }
966 let non_item_span = self.token.span;
968 let is_let = self.token.is_keyword(kw::Let);
969
970 let mut err =
971 self.dcx().struct_span_err(non_item_span, "non-item in item list");
972 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);
973 if is_let {
974 err.span_suggestion_verbose(
975 non_item_span,
976 "consider using `const` instead of `let` for associated const",
977 "const",
978 Applicability::MachineApplicable,
979 );
980 } else {
981 err.span_label(open_brace_span, "item list starts here")
982 .span_label(non_item_span, "non-item starts here")
983 .span_label(self.prev_token.span, "item list ends here");
984 }
985 if is_unnecessary_semicolon {
986 err.span_suggestion(
987 semicolon_span,
988 "consider removing this semicolon",
989 "",
990 Applicability::MaybeIncorrect,
991 );
992 }
993 err.emit();
994 break;
995 }
996 Ok(Some(item)) => items.extend(item),
997 Err(err) => {
998 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);
999 err.with_span_label(
1000 open_brace_span,
1001 "while parsing this item list starting here",
1002 )
1003 .with_span_label(self.prev_token.span, "the item list ends here")
1004 .emit();
1005 break;
1006 }
1007 }
1008 }
1009 Ok(items)
1010 }
1011
1012 fn recover_doc_comment_before_brace(&mut self) -> bool {
1014 if let token::DocComment(..) = self.token.kind {
1015 if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
1016 {
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!(
1018 self.dcx(),
1019 self.token.span,
1020 E0584,
1021 "found a documentation comment that doesn't document anything",
1022 )
1023 .with_span_label(self.token.span, "this doc comment doesn't document anything")
1024 .with_help(
1025 "doc comments must come before what they document, if a comment was \
1026 intended use `//`",
1027 )
1028 .emit();
1029 self.bump();
1030 return true;
1031 }
1032 }
1033 false
1034 }
1035
1036 fn parse_defaultness(&mut self) -> Defaultness {
1038 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))
1042 && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
1043 {
1044 self.psess.gated_spans.gate(sym::specialization, self.token.span);
1045 self.bump(); Defaultness::Default(self.prev_token_uninterpolated_span())
1047 } 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)) {
1048 self.psess.gated_spans.gate(sym::final_associated_functions, self.prev_token.span);
1049 Defaultness::Final(self.prev_token_uninterpolated_span())
1050 } else {
1051 Defaultness::Implicit
1052 }
1053 }
1054
1055 fn is_trait_with_maybe_impl_restriction_in_front(&self, dist: usize) -> bool {
1057 if self.is_keyword_ahead(dist, &[kw::Trait]) {
1059 return true;
1060 }
1061 if !self.is_keyword_ahead(dist, &[kw::Impl])
1063 || !self.look_ahead(dist + 1, |t| t == &token::OpenParen)
1064 {
1065 return false;
1066 }
1067 if self.is_keyword_ahead(dist + 2, &[kw::Crate, kw::Super, kw::SelfLower])
1069 && self.look_ahead(dist + 3, |t| t == &token::CloseParen)
1070 && self.is_keyword_ahead(dist + 4, &[kw::Trait])
1071 {
1072 return true;
1073 }
1074 self.tree_look_ahead(dist + 2, |t| {
1079 if let TokenTree::Token(token, _) = t { token.is_keyword(kw::Trait) } else { false }
1080 })
1081 .unwrap_or(false)
1082 }
1083
1084 fn check_trait_front_matter(&mut self) -> bool {
1086 if self.is_trait_with_maybe_impl_restriction_in_front(0) {
1088 return true;
1089 }
1090 if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Auto,
token_type: crate::parser::token_type::TokenType::KwAuto,
}exp!(Auto)) && self.is_trait_with_maybe_impl_restriction_in_front(1) {
1092 return true;
1093 }
1094 if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe))
1096 && (self.is_trait_with_maybe_impl_restriction_in_front(1)
1097 || self.is_keyword_ahead(1, &[kw::Auto])
1098 && self.is_trait_with_maybe_impl_restriction_in_front(2))
1099 {
1100 return true;
1101 }
1102 if !self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) {
1104 return false;
1105 }
1106 if self.is_trait_with_maybe_impl_restriction_in_front(1) {
1108 return true;
1109 }
1110 if self.is_keyword_ahead(1, &[kw::Unsafe, kw::Auto])
1112 && self.is_trait_with_maybe_impl_restriction_in_front(2)
1113 {
1114 return true;
1115 }
1116 self.is_keyword_ahead(1, &[kw::Unsafe])
1118 && self.is_keyword_ahead(2, &[kw::Auto])
1119 && self.is_trait_with_maybe_impl_restriction_in_front(3)
1120 }
1121
1122 fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
1129 let constness = self.parse_constness(Case::Sensitive);
1130 if let Const::Yes(span) = constness {
1131 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1132 }
1133 let safety = self.parse_safety(Case::Sensitive);
1134 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)) {
1136 self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
1137 IsAuto::Yes
1138 } else {
1139 IsAuto::No
1140 };
1141
1142 let impl_restriction = self.parse_impl_restriction()?;
1143
1144 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait))?;
1145 let ident = self.parse_ident()?;
1146 let mut generics = self.parse_generics()?;
1147
1148 let had_colon = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon));
1150 let span_at_colon = self.prev_token.span;
1151 let bounds = if had_colon { self.parse_generic_bounds()? } else { Vec::new() };
1152
1153 let span_before_eq = self.prev_token.span;
1154 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1155 if had_colon {
1157 let span = span_at_colon.to(span_before_eq);
1158 self.dcx().emit_err(errors::BoundsNotAllowedOnTraitAliases { span });
1159 }
1160
1161 let bounds = self.parse_generic_bounds()?;
1162 generics.where_clause = self.parse_where_clause()?;
1163 self.expect_semi()?;
1164
1165 let whole_span = lo.to(self.prev_token.span);
1166 if is_auto == IsAuto::Yes {
1167 self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span });
1168 }
1169 if let Safety::Unsafe(_) = safety {
1170 self.dcx().emit_err(errors::TraitAliasCannotBeUnsafe { span: whole_span });
1171 }
1172 if let RestrictionKind::Restricted { .. } = impl_restriction.kind {
1173 self.dcx().emit_err(errors::TraitAliasCannotBeImplRestricted { span: whole_span });
1174 }
1175
1176 self.psess.gated_spans.gate(sym::trait_alias, whole_span);
1177
1178 Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
1179 } else {
1180 generics.where_clause = self.parse_where_clause()?;
1182 let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
1183 Ok(ItemKind::Trait(Box::new(Trait {
1184 constness,
1185 is_auto,
1186 safety,
1187 impl_restriction,
1188 ident,
1189 generics,
1190 bounds,
1191 items,
1192 })))
1193 }
1194 }
1195
1196 pub fn parse_impl_item(
1197 &mut self,
1198 force_collect: ForceCollect,
1199 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1200 let fn_parse_mode =
1201 FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
1202 self.parse_assoc_item(fn_parse_mode, force_collect)
1203 }
1204
1205 pub fn parse_trait_item(
1206 &mut self,
1207 force_collect: ForceCollect,
1208 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1209 let fn_parse_mode = FnParseMode {
1210 req_name: |edition, _| edition >= Edition::Edition2018,
1211 context: FnContext::Trait,
1212 req_body: false,
1213 };
1214 self.parse_assoc_item(fn_parse_mode, force_collect)
1215 }
1216
1217 fn parse_assoc_item(
1219 &mut self,
1220 fn_parse_mode: FnParseMode,
1221 force_collect: ForceCollect,
1222 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1223 Ok(self
1224 .parse_item_(
1225 fn_parse_mode,
1226 force_collect,
1227 AllowConstBlockItems::DoesNotMatter, )?
1229 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1230 let kind = match AssocItemKind::try_from(kind) {
1231 Ok(kind) => kind,
1232 Err(kind) => match kind {
1233 ItemKind::Static(box StaticItem {
1234 ident,
1235 ty,
1236 safety: _,
1237 mutability: _,
1238 expr,
1239 define_opaque,
1240 eii_impls: _,
1241 }) => {
1242 self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
1243 AssocItemKind::Const(Box::new(ConstItem {
1244 defaultness: Defaultness::Implicit,
1245 ident,
1246 generics: Generics::default(),
1247 ty,
1248 rhs_kind: ConstItemRhsKind::Body { rhs: expr },
1249 define_opaque,
1250 }))
1251 }
1252 _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
1253 },
1254 };
1255 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1256 }))
1257 }
1258
1259 fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
1265 let ident = self.parse_ident()?;
1266 let mut generics = self.parse_generics()?;
1267
1268 let bounds = 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 { Vec::new() };
1270 generics.where_clause = self.parse_where_clause()?;
1271
1272 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 };
1273
1274 let after_where_clause = self.parse_where_clause()?;
1275
1276 self.expect_semi()?;
1277
1278 Ok(ItemKind::TyAlias(Box::new(TyAlias {
1279 defaultness,
1280 ident,
1281 generics,
1282 after_where_clause,
1283 bounds,
1284 ty,
1285 })))
1286 }
1287
1288 fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
1298 let lo = self.token.span;
1299
1300 let mut prefix =
1301 ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo(), tokens: None };
1302 let kind =
1303 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() {
1304 let mod_sep_ctxt = self.token.span.ctxt();
1306 if self.eat_path_sep() {
1307 prefix
1308 .segments
1309 .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
1310 }
1311
1312 self.parse_use_tree_glob_or_nested()?
1313 } else {
1314 prefix = self.parse_path(PathStyle::Mod)?;
1316
1317 if self.eat_path_sep() {
1318 self.parse_use_tree_glob_or_nested()?
1319 } else {
1320 while self.eat_noexpect(&token::Colon) {
1322 self.dcx()
1323 .emit_err(errors::SingleColonImportPath { span: self.prev_token.span });
1324
1325 self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
1327 prefix.span = lo.to(self.prev_token.span);
1328 }
1329
1330 UseTreeKind::Simple(self.parse_rename()?)
1331 }
1332 };
1333
1334 Ok(UseTree { prefix, kind })
1335 }
1336
1337 fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
1339 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
1340 UseTreeKind::Glob(self.prev_token.span)
1341 } else {
1342 let lo = self.token.span;
1343 UseTreeKind::Nested {
1344 items: self.parse_use_tree_list()?,
1345 span: lo.to(self.prev_token.span),
1346 }
1347 })
1348 }
1349
1350 fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
1356 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| {
1357 p.recover_vcs_conflict_marker();
1358 Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
1359 })
1360 .map(|(r, _)| r)
1361 }
1362
1363 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1364 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)) {
1365 self.parse_ident_or_underscore().map(Some)
1366 } else {
1367 Ok(None)
1368 }
1369 }
1370
1371 fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
1372 match self.token.ident() {
1373 Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
1374 self.bump();
1375 Ok(ident)
1376 }
1377 _ => self.parse_ident(),
1378 }
1379 }
1380
1381 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1390 let orig_ident = self.parse_crate_name_with_dashes()?;
1392 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1393 (Some(orig_ident.name), rename)
1394 } else {
1395 (None, orig_ident)
1396 };
1397 self.expect_semi()?;
1398 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1399 }
1400
1401 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1402 let ident = if self.token.is_keyword(kw::SelfLower) {
1403 self.parse_path_segment_ident()
1404 } else {
1405 self.parse_ident()
1406 }?;
1407
1408 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1409 if self.token != dash.tok {
1410 return Ok(ident);
1411 }
1412
1413 let mut dashes = ::alloc::vec::Vec::new()vec![];
1415 let mut idents = ::alloc::vec::Vec::new()vec![];
1416 while self.eat(dash) {
1417 dashes.push(self.prev_token.span);
1418 idents.push(self.parse_ident()?);
1419 }
1420
1421 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1422 let mut fixed_name = ident.name.to_string();
1423 for part in idents {
1424 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1425 }
1426
1427 self.dcx().emit_err(errors::ExternCrateNameWithDashes {
1428 span: fixed_name_sp,
1429 sugg: errors::ExternCrateNameWithDashesSugg { dashes },
1430 });
1431
1432 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1433 }
1434
1435 fn parse_item_foreign_mod(
1446 &mut self,
1447 attrs: &mut AttrVec,
1448 mut safety: Safety,
1449 ) -> PResult<'a, ItemKind> {
1450 let extern_span = self.prev_token_uninterpolated_span();
1451 let abi = self.parse_abi(); if safety == Safety::Default
1454 && self.token.is_keyword(kw::Unsafe)
1455 && self.look_ahead(1, |t| *t == token::OpenBrace)
1456 {
1457 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();
1458 safety = Safety::Unsafe(self.token.span);
1459 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));
1460 }
1461 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1462 extern_span,
1463 safety,
1464 abi,
1465 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1466 }))
1467 }
1468
1469 pub fn parse_foreign_item(
1471 &mut self,
1472 force_collect: ForceCollect,
1473 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1474 let fn_parse_mode = FnParseMode {
1475 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1476 context: FnContext::Free,
1477 req_body: false,
1478 };
1479 Ok(self
1480 .parse_item_(
1481 fn_parse_mode,
1482 force_collect,
1483 AllowConstBlockItems::DoesNotMatter, )?
1485 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1486 let kind = match ForeignItemKind::try_from(kind) {
1487 Ok(kind) => kind,
1488 Err(kind) => match kind {
1489 ItemKind::Const(box ConstItem { ident, ty, rhs_kind, .. }) => {
1490 let const_span = Some(span.with_hi(ident.span.lo()))
1491 .filter(|span| span.can_be_used_for_suggestions());
1492 self.dcx().emit_err(errors::ExternItemCannotBeConst {
1493 ident_span: ident.span,
1494 const_span,
1495 });
1496 ForeignItemKind::Static(Box::new(StaticItem {
1497 ident,
1498 ty,
1499 mutability: Mutability::Not,
1500 expr: match rhs_kind {
1501 ConstItemRhsKind::Body { rhs } => rhs,
1502 ConstItemRhsKind::TypeConst { rhs: Some(anon) } => {
1503 Some(anon.value)
1504 }
1505 ConstItemRhsKind::TypeConst { rhs: None } => None,
1506 },
1507 safety: Safety::Default,
1508 define_opaque: None,
1509 eii_impls: ThinVec::default(),
1510 }))
1511 }
1512 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1513 },
1514 };
1515 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1516 }))
1517 }
1518
1519 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1520 let span = self.psess.source_map().guess_head_span(span);
1522 let descr = kind.descr();
1523 let help = match kind {
1524 ItemKind::DelegationMac(box DelegationMac {
1525 suffixes: DelegationSuffixes::Glob(_),
1526 ..
1527 }) => false,
1528 _ => true,
1529 };
1530 self.dcx().emit_err(errors::BadItemKind { span, descr, ctx, help });
1531 None
1532 }
1533
1534 fn is_use_closure(&self) -> bool {
1535 if self.token.is_keyword(kw::Use) {
1536 self.look_ahead(1, |token| {
1538 let dist =
1540 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1541
1542 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))
1543 })
1544 } else {
1545 false
1546 }
1547 }
1548
1549 fn is_unsafe_foreign_mod(&self) -> bool {
1550 if !self.token.is_keyword(kw::Unsafe) {
1552 return false;
1553 }
1554 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1556 return false;
1557 }
1558
1559 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1561
1562 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, _)))
1567 == Some(true)
1568 }
1569
1570 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1571 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) {
1572 !self.look_ahead(1, |token| {
1574 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1575 return true;
1576 }
1577 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1578 })
1579 } else {
1580 (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)
1582 || 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))
1583 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1584 };
1585
1586 if is_global_static {
1587 let safety = self.parse_safety(case);
1588 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);
1589 Some(safety)
1590 } else {
1591 None
1592 }
1593 }
1594
1595 fn recover_const_mut(&mut self, const_span: Span) {
1597 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)) {
1598 let span = self.prev_token.span;
1599 self.dcx()
1600 .emit_err(errors::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1601 } 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)) {
1602 let span = self.prev_token.span;
1603 self.dcx().emit_err(errors::ConstLetMutuallyExclusive { span: const_span.to(span) });
1604 }
1605 }
1606
1607 fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
1608 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1609 let const_span = self.prev_token.span;
1610 self.psess.gated_spans.gate(sym::const_block_items, const_span);
1611 let block = self.parse_block()?;
1612 Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
1613 }
1614
1615 fn parse_static_item(
1622 &mut self,
1623 safety: Safety,
1624 mutability: Mutability,
1625 ) -> PResult<'a, ItemKind> {
1626 let ident = self.parse_ident()?;
1627
1628 if self.token == TokenKind::Lt && self.may_recover() {
1629 let generics = self.parse_generics()?;
1630 self.dcx().emit_err(errors::StaticWithGenerics { span: generics.span });
1631 }
1632
1633 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))) {
1636 (true, false) => self.parse_ty()?,
1637 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1640 };
1641
1642 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 };
1643
1644 self.expect_semi()?;
1645
1646 let item = StaticItem {
1647 ident,
1648 ty,
1649 safety,
1650 mutability,
1651 expr,
1652 define_opaque: None,
1653 eii_impls: ThinVec::default(),
1654 };
1655 Ok(ItemKind::Static(Box::new(item)))
1656 }
1657
1658 fn parse_const_item(
1667 &mut self,
1668 const_arg: bool,
1669 const_span: Span,
1670 ) -> PResult<'a, (Ident, Generics, Box<Ty>, ConstItemRhsKind)> {
1671 let ident = self.parse_ident_or_underscore()?;
1672
1673 let mut generics = self.parse_generics()?;
1674
1675 if !generics.span.is_empty() {
1678 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1679 }
1680
1681 let ty = match (
1684 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1685 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)),
1686 ) {
1687 (true, false) => self.parse_ty()?,
1688 (colon, _) => self.recover_missing_global_item_type(colon, None),
1690 };
1691
1692 let before_where_clause =
1695 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1696
1697 let rhs = match (self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)), const_arg) {
1698 (true, true) => ConstItemRhsKind::TypeConst {
1699 rhs: Some(self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?),
1700 },
1701 (true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) },
1702 (false, true) => ConstItemRhsKind::TypeConst { rhs: None },
1703 (false, false) => ConstItemRhsKind::Body { rhs: None },
1704 };
1705
1706 let after_where_clause = self.parse_where_clause()?;
1707
1708 if before_where_clause.has_where_token
1712 && let Some(rhs_span) = rhs.span()
1713 {
1714 self.dcx().emit_err(errors::WhereClauseBeforeConstBody {
1715 span: before_where_clause.span,
1716 name: ident.span,
1717 body: rhs_span,
1718 sugg: if !after_where_clause.has_where_token {
1719 self.psess.source_map().span_to_snippet(rhs_span).ok().map(|body_s| {
1720 errors::WhereClauseBeforeConstBodySugg {
1721 left: before_where_clause.span.shrink_to_lo(),
1722 snippet: body_s,
1723 right: before_where_clause.span.shrink_to_hi().to(rhs_span),
1724 }
1725 })
1726 } else {
1727 None
1730 },
1731 });
1732 }
1733
1734 let mut predicates = before_where_clause.predicates;
1741 predicates.extend(after_where_clause.predicates);
1742 let where_clause = WhereClause {
1743 has_where_token: before_where_clause.has_where_token
1744 || after_where_clause.has_where_token,
1745 predicates,
1746 span: if after_where_clause.has_where_token {
1747 after_where_clause.span
1748 } else {
1749 before_where_clause.span
1750 },
1751 };
1752
1753 if where_clause.has_where_token {
1754 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1755 }
1756
1757 generics.where_clause = where_clause;
1758
1759 if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
1760 return Ok((ident, generics, ty, ConstItemRhsKind::Body { rhs: Some(rhs) }));
1761 }
1762 self.expect_semi()?;
1763
1764 Ok((ident, generics, ty, rhs))
1765 }
1766
1767 fn recover_missing_global_item_type(
1770 &mut self,
1771 colon_present: bool,
1772 m: Option<Mutability>,
1773 ) -> Box<Ty> {
1774 let kind = match m {
1777 Some(Mutability::Mut) => "static mut",
1778 Some(Mutability::Not) => "static",
1779 None => "const",
1780 };
1781
1782 let colon = match colon_present {
1783 true => "",
1784 false => ":",
1785 };
1786
1787 let span = self.prev_token.span.shrink_to_hi();
1788 let err = self.dcx().create_err(errors::MissingConstType { span, colon, kind });
1789 err.stash(span, StashKey::ItemNoType);
1790
1791 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None })
1794 }
1795
1796 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1798 if self.token.is_keyword(kw::Struct) {
1799 let span = self.prev_token.span.to(self.token.span);
1800 let err = errors::EnumStructMutuallyExclusive { span };
1801 if self.look_ahead(1, |t| t.is_ident()) {
1802 self.bump();
1803 self.dcx().emit_err(err);
1804 } else {
1805 return Err(self.dcx().create_err(err));
1806 }
1807 }
1808
1809 let prev_span = self.prev_token.span;
1810 let ident = self.parse_ident()?;
1811 let mut generics = self.parse_generics()?;
1812 generics.where_clause = self.parse_where_clause()?;
1813
1814 let (variants, _) = if self.token == TokenKind::Semi {
1816 self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
1817 self.bump();
1818 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1819 } else {
1820 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| {
1821 p.parse_enum_variant(ident.span)
1822 })
1823 .map_err(|mut err| {
1824 err.span_label(ident.span, "while parsing this enum");
1825 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1827 let snapshot = self.create_snapshot_for_diagnostic();
1828 self.bump();
1829 match self.parse_ty() {
1830 Ok(_) => {
1831 err.span_suggestion_verbose(
1832 prev_span,
1833 "perhaps you meant to use `struct` here",
1834 "struct",
1835 Applicability::MaybeIncorrect,
1836 );
1837 }
1838 Err(e) => {
1839 e.cancel();
1840 }
1841 }
1842 self.restore_snapshot(snapshot);
1843 }
1844 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1845 self.bump(); err
1847 })?
1848 };
1849
1850 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1851 Ok(ItemKind::Enum(ident, generics, enum_definition))
1852 }
1853
1854 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1855 self.recover_vcs_conflict_marker();
1856 let variant_attrs = self.parse_outer_attributes()?;
1857 self.recover_vcs_conflict_marker();
1858 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1859 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1860 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1861 let vlo = this.token.span;
1862
1863 let vis = this.parse_visibility(FollowedByType::No)?;
1864 if !this.recover_nested_adt_item(kw::Enum)? {
1865 return Ok((None, Trailing::No, UsePreAttrPos::No));
1866 }
1867 let ident = this.parse_field_ident("enum", vlo)?;
1868
1869 if this.token == token::Bang {
1870 if let Err(err) = this.unexpected() {
1871 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();
1872 }
1873
1874 this.bump();
1875 this.parse_delim_args()?;
1876
1877 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1878 }
1879
1880 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)) {
1881 let (fields, recovered) =
1883 match this.parse_record_struct_body("struct", ident.span, false) {
1884 Ok((fields, recovered)) => (fields, recovered),
1885 Err(mut err) => {
1886 if this.token == token::Colon {
1887 return Err(err);
1889 }
1890 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1891 this.bump(); err.span_label(span, "while parsing this enum");
1893 err.help(help);
1894 let guar = err.emit();
1895 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1896 }
1897 };
1898 VariantData::Struct { fields, recovered }
1899 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1900 let body = match this.parse_tuple_struct_body() {
1901 Ok(body) => body,
1902 Err(mut err) => {
1903 if this.token == token::Colon {
1904 return Err(err);
1906 }
1907 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
1908 this.bump(); err.span_label(span, "while parsing this enum");
1910 err.help(help);
1911 err.emit();
1912 ::thin_vec::ThinVec::new()thin_vec![]
1913 }
1914 };
1915 VariantData::Tuple(body, DUMMY_NODE_ID)
1916 } else {
1917 VariantData::Unit(DUMMY_NODE_ID)
1918 };
1919
1920 let disr_expr = if this.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1921 Some(this.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?)
1922 } else {
1923 None
1924 };
1925
1926 let vr = ast::Variant {
1927 ident,
1928 vis,
1929 id: DUMMY_NODE_ID,
1930 attrs: variant_attrs,
1931 data: struct_def,
1932 disr_expr,
1933 span: vlo.to(this.prev_token.span),
1934 is_placeholder: false,
1935 };
1936
1937 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
1938 })
1939 .map_err(|mut err| {
1940 err.help(help);
1941 err
1942 })
1943 }
1944
1945 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
1947 let ident = self.parse_ident()?;
1948
1949 let mut generics = self.parse_generics()?;
1950
1951 let vdata = if self.token.is_keyword(kw::Where) {
1966 let tuple_struct_body;
1967 (generics.where_clause, tuple_struct_body) =
1968 self.parse_struct_where_clause(ident, generics.span)?;
1969
1970 if let Some(body) = tuple_struct_body {
1971 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
1973 self.expect_semi()?;
1974 body
1975 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1976 VariantData::Unit(DUMMY_NODE_ID)
1978 } else {
1979 let (fields, recovered) = self.parse_record_struct_body(
1981 "struct",
1982 ident.span,
1983 generics.where_clause.has_where_token,
1984 )?;
1985 VariantData::Struct { fields, recovered }
1986 }
1987 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1989 VariantData::Unit(DUMMY_NODE_ID)
1990 } else if self.token == token::OpenBrace {
1992 let (fields, recovered) = self.parse_record_struct_body(
1993 "struct",
1994 ident.span,
1995 generics.where_clause.has_where_token,
1996 )?;
1997 VariantData::Struct { fields, recovered }
1998 } else if self.token == token::OpenParen {
2000 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
2001 generics.where_clause = self.parse_where_clause()?;
2002 self.expect_semi()?;
2003 body
2004 } else {
2005 let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
2006 return Err(self.dcx().create_err(err));
2007 };
2008
2009 Ok(ItemKind::Struct(ident, generics, vdata))
2010 }
2011
2012 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
2014 let ident = self.parse_ident()?;
2015
2016 let mut generics = self.parse_generics()?;
2017
2018 let vdata = if self.token.is_keyword(kw::Where) {
2019 generics.where_clause = self.parse_where_clause()?;
2020 let (fields, recovered) = self.parse_record_struct_body(
2021 "union",
2022 ident.span,
2023 generics.where_clause.has_where_token,
2024 )?;
2025 VariantData::Struct { fields, recovered }
2026 } else if self.token == token::OpenBrace {
2027 let (fields, recovered) = self.parse_record_struct_body(
2028 "union",
2029 ident.span,
2030 generics.where_clause.has_where_token,
2031 )?;
2032 VariantData::Struct { fields, recovered }
2033 } else {
2034 let token_str = super::token_descr(&self.token);
2035 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}");
2036 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2037 err.span_label(self.token.span, "expected `where` or `{` after union name");
2038 return Err(err);
2039 };
2040
2041 Ok(ItemKind::Union(ident, generics, vdata))
2042 }
2043
2044 pub(crate) fn parse_record_struct_body(
2049 &mut self,
2050 adt_ty: &str,
2051 ident_span: Span,
2052 parsed_where: bool,
2053 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
2054 let mut fields = ThinVec::new();
2055 let mut recovered = Recovered::No;
2056 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2057 while self.token != token::CloseBrace {
2058 match self.parse_field_def(adt_ty, ident_span) {
2059 Ok(field) => {
2060 fields.push(field);
2061 }
2062 Err(mut err) => {
2063 self.consume_block(
2064 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
2065 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
2066 ConsumeClosingDelim::No,
2067 );
2068 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}"));
2069 let guar = err.emit();
2070 recovered = Recovered::Yes(guar);
2071 break;
2072 }
2073 }
2074 }
2075 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
2076 } else {
2077 let token_str = super::token_descr(&self.token);
2078 let where_str = if parsed_where { "" } else { "`where`, or " };
2079 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}");
2080 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2081 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",));
2082 return Err(err);
2083 }
2084
2085 Ok((fields, recovered))
2086 }
2087
2088 fn parse_unsafe_field(&mut self) -> Safety {
2089 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)) {
2091 let span = self.prev_token.span;
2092 self.psess.gated_spans.gate(sym::unsafe_fields, span);
2093 Safety::Unsafe(span)
2094 } else {
2095 Safety::Default
2096 }
2097 }
2098
2099 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
2100 self.parse_paren_comma_seq(|p| {
2103 let attrs = p.parse_outer_attributes()?;
2104 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
2105 let mut snapshot = None;
2106 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
2107 snapshot = Some(p.create_snapshot_for_diagnostic());
2111 }
2112 let lo = p.token.span;
2113 let vis = match p.parse_visibility(FollowedByType::Yes) {
2114 Ok(vis) => vis,
2115 Err(err) => {
2116 if let Some(ref mut snapshot) = snapshot {
2117 snapshot.recover_vcs_conflict_marker();
2118 }
2119 return Err(err);
2120 }
2121 };
2122 let ty = match p.parse_ty() {
2125 Ok(ty) => ty,
2126 Err(err) => {
2127 if let Some(ref mut snapshot) = snapshot {
2128 snapshot.recover_vcs_conflict_marker();
2129 }
2130 return Err(err);
2131 }
2132 };
2133 let mut default = None;
2134 if p.token == token::Eq {
2135 let mut snapshot = p.create_snapshot_for_diagnostic();
2136 snapshot.bump();
2137 match snapshot.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst) {
2138 Ok(const_expr) => {
2139 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2140 p.psess.gated_spans.gate(sym::default_field_values, sp);
2141 p.restore_snapshot(snapshot);
2142 default = Some(const_expr);
2143 }
2144 Err(err) => {
2145 err.cancel();
2146 }
2147 }
2148 }
2149
2150 Ok((
2151 FieldDef {
2152 span: lo.to(ty.span),
2153 vis,
2154 safety: Safety::Default,
2155 ident: None,
2156 id: DUMMY_NODE_ID,
2157 ty,
2158 default,
2159 attrs,
2160 is_placeholder: false,
2161 },
2162 Trailing::from(p.token == token::Comma),
2163 UsePreAttrPos::No,
2164 ))
2165 })
2166 })
2167 .map(|(r, _)| r)
2168 }
2169
2170 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2172 self.recover_vcs_conflict_marker();
2173 let attrs = self.parse_outer_attributes()?;
2174 self.recover_vcs_conflict_marker();
2175 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2176 let lo = this.token.span;
2177 let vis = this.parse_visibility(FollowedByType::No)?;
2178 let safety = this.parse_unsafe_field();
2179 this.parse_single_struct_field(adt_ty, lo, vis, safety, attrs, ident_span)
2180 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2181 })
2182 }
2183
2184 fn parse_single_struct_field(
2186 &mut self,
2187 adt_ty: &str,
2188 lo: Span,
2189 vis: Visibility,
2190 safety: Safety,
2191 attrs: AttrVec,
2192 ident_span: Span,
2193 ) -> PResult<'a, FieldDef> {
2194 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, safety, attrs)?;
2195 match self.token.kind {
2196 token::Comma => {
2197 self.bump();
2198 }
2199 token::Semi => {
2200 self.bump();
2201 let sp = self.prev_token.span;
2202 let mut err =
2203 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 `,`"));
2204 err.span_suggestion_short(
2205 sp,
2206 "replace `;` with `,`",
2207 ",",
2208 Applicability::MachineApplicable,
2209 );
2210 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}"));
2211 err.emit();
2212 }
2213 token::CloseBrace => {}
2214 token::DocComment(..) => {
2215 let previous_span = self.prev_token.span;
2216 let mut err = errors::DocCommentDoesNotDocumentAnything {
2217 span: self.token.span,
2218 missing_comma: None,
2219 };
2220 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 {
2222 self.dcx().emit_err(err);
2223 } else {
2224 let sp = previous_span.shrink_to_hi();
2225 err.missing_comma = Some(sp);
2226 return Err(self.dcx().create_err(err));
2227 }
2228 }
2229 _ => {
2230 let sp = self.prev_token.span.shrink_to_hi();
2231 let msg =
2232 ::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));
2233
2234 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2236 && let Some(last_segment) = segments.last()
2237 {
2238 let guar = self.check_trailing_angle_brackets(
2239 last_segment,
2240 &[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)],
2241 );
2242 if let Some(_guar) = guar {
2243 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2246
2247 return Ok(a_var);
2250 }
2251 }
2252
2253 let mut err = self.dcx().struct_span_err(sp, msg);
2254
2255 if self.token.is_ident()
2256 || (self.token == TokenKind::Pound
2257 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2258 {
2259 err.span_suggestion(
2262 sp,
2263 "try adding a comma",
2264 ",",
2265 Applicability::MachineApplicable,
2266 );
2267 err.emit();
2268 } else {
2269 return Err(err);
2270 }
2271 }
2272 }
2273 Ok(a_var)
2274 }
2275
2276 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2277 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)) {
2278 let sm = self.psess.source_map();
2279 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2280 let semi_typo = self.token == token::Semi
2281 && self.look_ahead(1, |t| {
2282 t.is_path_start()
2283 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2286 (Ok(l), Ok(r)) => l.line == r.line,
2287 _ => true,
2288 }
2289 });
2290 if eq_typo || semi_typo {
2291 self.bump();
2292 err.with_span_suggestion_short(
2294 self.prev_token.span,
2295 "field names and their types are separated with `:`",
2296 ":",
2297 Applicability::MachineApplicable,
2298 )
2299 .emit();
2300 } else {
2301 return Err(err);
2302 }
2303 }
2304 Ok(())
2305 }
2306
2307 fn parse_name_and_ty(
2309 &mut self,
2310 adt_ty: &str,
2311 lo: Span,
2312 vis: Visibility,
2313 safety: Safety,
2314 attrs: AttrVec,
2315 ) -> PResult<'a, FieldDef> {
2316 let name = self.parse_field_ident(adt_ty, lo)?;
2317 if self.token == token::Bang {
2318 if let Err(mut err) = self.unexpected() {
2319 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2321 return Err(err);
2322 }
2323 }
2324 self.expect_field_ty_separator()?;
2325 let ty = self.parse_ty()?;
2326 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2327 self.dcx()
2328 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2329 .with_span_suggestion_verbose(
2330 self.token.span,
2331 "write a path separator here",
2332 "::",
2333 Applicability::MaybeIncorrect,
2334 )
2335 .emit();
2336 }
2337 let default = if self.token == token::Eq {
2338 self.bump();
2339 let const_expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
2340 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2341 self.psess.gated_spans.gate(sym::default_field_values, sp);
2342 Some(const_expr)
2343 } else {
2344 None
2345 };
2346 Ok(FieldDef {
2347 span: lo.to(self.prev_token.span),
2348 ident: Some(name),
2349 vis,
2350 safety,
2351 id: DUMMY_NODE_ID,
2352 ty,
2353 default,
2354 attrs,
2355 is_placeholder: false,
2356 })
2357 }
2358
2359 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2362 let (ident, is_raw) = self.ident_or_err(true)?;
2363 if is_raw == IdentIsRaw::No && ident.is_reserved() {
2364 let snapshot = self.create_snapshot_for_diagnostic();
2365 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2366 let inherited_vis =
2367 Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
2368 let fn_parse_mode =
2370 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2371 match self.parse_fn(
2372 &mut AttrVec::new(),
2373 fn_parse_mode,
2374 lo,
2375 &inherited_vis,
2376 Case::Insensitive,
2377 ) {
2378 Ok(_) => {
2379 self.dcx().struct_span_err(
2380 lo.to(self.prev_token.span),
2381 ::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"),
2382 )
2383 .with_help(
2384 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2385 )
2386 .with_help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information")
2387 }
2388 Err(err) => {
2389 err.cancel();
2390 self.restore_snapshot(snapshot);
2391 self.expected_ident_found_err()
2392 }
2393 }
2394 } 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)) {
2395 match self.parse_item_struct() {
2396 Ok(item) => {
2397 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2398 self.dcx()
2399 .struct_span_err(
2400 lo.with_hi(ident.span.hi()),
2401 ::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"),
2402 )
2403 .with_help(
2404 "consider creating a new `struct` definition instead of nesting",
2405 )
2406 }
2407 Err(err) => {
2408 err.cancel();
2409 self.restore_snapshot(snapshot);
2410 self.expected_ident_found_err()
2411 }
2412 }
2413 } else {
2414 let mut err = self.expected_ident_found_err();
2415 if self.eat_keyword_noexpect(kw::Let)
2416 && let removal_span = self.prev_token.span.until(self.token.span)
2417 && let Ok(ident) = self
2418 .parse_ident_common(false)
2419 .map_err(|err| err.cancel())
2421 && self.token == TokenKind::Colon
2422 {
2423 err.span_suggestion(
2424 removal_span,
2425 "remove this `let` keyword",
2426 String::new(),
2427 Applicability::MachineApplicable,
2428 );
2429 err.note("the `let` keyword is not allowed in `struct` fields");
2430 err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
2431 err.emit();
2432 return Ok(ident);
2433 } else {
2434 self.restore_snapshot(snapshot);
2435 }
2436 err
2437 };
2438 return Err(err);
2439 }
2440 self.bump();
2441 Ok(ident)
2442 }
2443
2444 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2452 let ident = self.parse_ident()?;
2453 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)) {
2454 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)) {
2456 let params = self.parse_token_tree(); let pspan = params.span();
2458 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2459 self.unexpected()?;
2460 }
2461 let body = self.parse_token_tree(); let bspan = body.span();
2464 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]);
2466 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2467 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2468 } else {
2469 self.unexpected_any()?
2470 };
2471
2472 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2473 Ok(ItemKind::MacroDef(
2474 ident,
2475 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2476 ))
2477 }
2478
2479 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2481 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)) {
2482 let macro_rules_span = self.token.span;
2483
2484 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2485 return IsMacroRulesItem::Yes { has_bang: true };
2486 } else if self.look_ahead(1, |t| t.is_ident()) {
2487 self.dcx().emit_err(errors::MacroRulesMissingBang {
2489 span: macro_rules_span,
2490 hi: macro_rules_span.shrink_to_hi(),
2491 });
2492
2493 return IsMacroRulesItem::Yes { has_bang: false };
2494 }
2495 }
2496
2497 IsMacroRulesItem::No
2498 }
2499
2500 fn parse_item_macro_rules(
2502 &mut self,
2503 vis: &Visibility,
2504 has_bang: bool,
2505 ) -> PResult<'a, ItemKind> {
2506 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 {
2509 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2511 let ident = self.parse_ident()?;
2512
2513 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2514 let span = self.prev_token.span;
2516 self.dcx().emit_err(errors::MacroNameRemoveBang { span });
2517 }
2518
2519 let body = self.parse_delim_args()?;
2520 self.eat_semi_for_macro_if_needed(&body, None);
2521 self.complain_if_pub_macro(vis, true);
2522
2523 Ok(ItemKind::MacroDef(
2524 ident,
2525 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2526 ))
2527 }
2528
2529 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2532 if let VisibilityKind::Inherited = vis.kind {
2533 return;
2534 }
2535
2536 let vstr = pprust::vis_to_string(vis);
2537 let vstr = vstr.trim_end();
2538 if macro_rules {
2539 self.dcx().emit_err(errors::MacroRulesVisibility { span: vis.span, vis: vstr });
2540 } else {
2541 self.dcx().emit_err(errors::MacroInvocationVisibility { span: vis.span, vis: vstr });
2542 }
2543 }
2544
2545 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
2546 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)) {
2547 self.report_invalid_macro_expansion_item(args, path);
2548 }
2549 }
2550
2551 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
2552 let span = args.dspan.entire();
2553 let mut err = self.dcx().struct_span_err(
2554 span,
2555 "macros that expand to items must be delimited with braces or followed by a semicolon",
2556 );
2557 if !span.from_expansion() {
2560 let DelimSpan { open, close } = args.dspan;
2561 if let Some(path) = path
2564 && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2565 && args.delim == Delimiter::Parenthesis
2566 {
2567 let replace =
2568 if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2569 err.multipart_suggestion(
2570 "to define a macro, remove the parentheses around the macro name",
2571 ::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())],
2572 Applicability::MachineApplicable,
2573 );
2574 } else {
2575 err.multipart_suggestion(
2576 "change the delimiters to curly braces",
2577 ::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())],
2578 Applicability::MaybeIncorrect,
2579 );
2580 err.span_suggestion(
2581 span.with_neighbor(self.token.span).shrink_to_hi(),
2582 "add a semicolon",
2583 ';',
2584 Applicability::MaybeIncorrect,
2585 );
2586 }
2587 }
2588 err.emit();
2589 }
2590
2591 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2594 if (self.token.is_keyword(kw::Enum)
2595 || self.token.is_keyword(kw::Struct)
2596 || self.token.is_keyword(kw::Union))
2597 && self.look_ahead(1, |t| t.is_ident())
2598 {
2599 let kw_token = self.token;
2600 let kw_str = pprust::token_to_string(&kw_token);
2601 let item = self.parse_item(
2602 ForceCollect::No,
2603 AllowConstBlockItems::DoesNotMatter, )?;
2605 let mut item = item.unwrap().span;
2606 if self.token == token::Comma {
2607 item = item.to(self.token.span);
2608 }
2609 self.dcx().emit_err(errors::NestedAdt {
2610 span: kw_token.span,
2611 item,
2612 kw_str,
2613 keyword: keyword.as_str(),
2614 });
2615 return Ok(false);
2617 }
2618 Ok(true)
2619 }
2620}
2621
2622type ReqName = fn(Edition, IsDotDotDot) -> bool;
2631
2632#[derive(#[automatically_derived]
impl ::core::marker::Copy for IsDotDotDot { }Copy, #[automatically_derived]
impl ::core::clone::Clone for IsDotDotDot {
#[inline]
fn clone(&self) -> IsDotDotDot { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for IsDotDotDot {
#[inline]
fn eq(&self, other: &IsDotDotDot) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
2633pub(crate) enum IsDotDotDot {
2634 Yes,
2635 No,
2636}
2637
2638#[derive(#[automatically_derived]
impl ::core::clone::Clone for FnParseMode {
#[inline]
fn clone(&self) -> FnParseMode {
let _: ::core::clone::AssertParamIsClone<ReqName>;
let _: ::core::clone::AssertParamIsClone<FnContext>;
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FnParseMode { }Copy)]
2646pub(crate) struct FnParseMode {
2647 pub(super) req_name: ReqName,
2673 pub(super) context: FnContext,
2676 pub(super) req_body: bool,
2695}
2696
2697#[derive(#[automatically_derived]
impl ::core::clone::Clone for FnContext {
#[inline]
fn clone(&self) -> FnContext { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FnContext { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for FnContext {
#[inline]
fn eq(&self, other: &FnContext) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FnContext {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
2700pub(crate) enum FnContext {
2701 Free,
2703 Trait,
2705 Impl,
2707}
2708
2709impl<'a> Parser<'a> {
2711 fn parse_fn(
2713 &mut self,
2714 attrs: &mut AttrVec,
2715 fn_parse_mode: FnParseMode,
2716 sig_lo: Span,
2717 vis: &Visibility,
2718 case: Case,
2719 ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
2720 let fn_span = self.token.span;
2721 let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; let decl = match self.parse_fn_decl(&fn_parse_mode, AllowPlus::Yes, RecoverReturnSign::Yes)
2725 {
2726 Ok(decl) => decl,
2727 Err(old_err) => {
2728 if self.token.is_keyword(kw::For) {
2730 old_err.cancel();
2731 return Err(self.dcx().create_err(errors::FnTypoWithImpl { fn_span }));
2732 } else {
2733 return Err(old_err);
2734 }
2735 }
2736 };
2737
2738 let fn_params_end = self.prev_token.span.shrink_to_hi();
2741
2742 let contract = self.parse_contract()?;
2743
2744 generics.where_clause = self.parse_where_clause()?; let fn_params_end =
2748 if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
2749
2750 let mut sig_hi = self.prev_token.span;
2751 let body =
2753 self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
2754 let fn_sig_span = sig_lo.to(sig_hi);
2755 Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
2756 }
2757
2758 fn error_fn_body_not_found(
2760 &mut self,
2761 ident_span: Span,
2762 req_body: bool,
2763 fn_params_end: Option<Span>,
2764 ) -> PResult<'a, ErrorGuaranteed> {
2765 let expected: &[_] =
2766 if req_body { &[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)] } else { &[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)] };
2767 match self.expected_one_of_not_found(&[], expected) {
2768 Ok(error_guaranteed) => Ok(error_guaranteed),
2769 Err(mut err) => {
2770 if self.token == token::CloseBrace {
2771 err.span_label(ident_span, "while parsing this `fn`");
2774 Ok(err.emit())
2775 } else if self.token == token::RArrow
2776 && let Some(fn_params_end) = fn_params_end
2777 {
2778 let fn_trait_span =
2784 [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
2785 if self.prev_token.is_ident_named(symbol) {
2786 Some(self.prev_token.span)
2787 } else {
2788 None
2789 }
2790 });
2791
2792 let arrow_span = self.token.span;
2797 let ty_span = match self.parse_ret_ty(
2798 AllowPlus::Yes,
2799 RecoverQPath::Yes,
2800 RecoverReturnSign::Yes,
2801 ) {
2802 Ok(ty_span) => ty_span.span().shrink_to_hi(),
2803 Err(parse_error) => {
2804 parse_error.cancel();
2805 return Err(err);
2806 }
2807 };
2808 let ret_ty_span = arrow_span.to(ty_span);
2809
2810 if let Some(fn_trait_span) = fn_trait_span {
2811 err.subdiagnostic(errors::FnTraitMissingParen { span: fn_trait_span });
2814 } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
2815 {
2816 err.primary_message(
2820 "return type should be specified after the function parameters",
2821 );
2822 err.subdiagnostic(errors::MisplacedReturnType {
2823 fn_params_end,
2824 snippet,
2825 ret_ty_span,
2826 });
2827 }
2828 Err(err)
2829 } else {
2830 Err(err)
2831 }
2832 }
2833 }
2834 }
2835
2836 fn parse_fn_body(
2840 &mut self,
2841 attrs: &mut AttrVec,
2842 ident: &Ident,
2843 sig_hi: &mut Span,
2844 req_body: bool,
2845 fn_params_end: Option<Span>,
2846 ) -> PResult<'a, Option<Box<Block>>> {
2847 let has_semi = if req_body {
2848 self.token == TokenKind::Semi
2849 } else {
2850 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))
2852 };
2853 let (inner_attrs, body) = if has_semi {
2854 self.expect_semi()?;
2856 *sig_hi = self.prev_token.span;
2857 (AttrVec::new(), None)
2858 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) || self.token.is_metavar_block() {
2859 let prev_in_fn_body = self.in_fn_body;
2860 self.in_fn_body = true;
2861 let res = self.parse_block_common(self.token.span, BlockCheckMode::Default, None).map(
2862 |(attrs, mut body)| {
2863 if let Some(guar) = self.fn_body_missing_semi_guar.take() {
2864 body.stmts.push(self.mk_stmt(
2865 body.span,
2866 StmtKind::Expr(self.mk_expr(body.span, ExprKind::Err(guar))),
2867 ));
2868 }
2869 (attrs, Some(body))
2870 },
2871 );
2872 self.in_fn_body = prev_in_fn_body;
2873 res?
2874 } else if self.token == token::Eq {
2875 self.bump(); let eq_sp = self.prev_token.span;
2878 let _ = self.parse_expr()?;
2879 self.expect_semi()?; let span = eq_sp.to(self.prev_token.span);
2881 let guar = self.dcx().emit_err(errors::FunctionBodyEqualsExpr {
2882 span,
2883 sugg: errors::FunctionBodyEqualsExprSugg { eq: eq_sp, semi: self.prev_token.span },
2884 });
2885 (AttrVec::new(), Some(self.mk_block_err(span, guar)))
2886 } else {
2887 self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
2888 (AttrVec::new(), None)
2889 };
2890 attrs.extend(inner_attrs);
2891 Ok(body)
2892 }
2893
2894 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2895 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2896 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)) {
2899 return true;
2900 }
2901 let mut i = 0;
2902 while i < ALL_QUALS.len() {
2903 let action = self.look_ahead(i + look_ahead, |token| {
2904 if token.is_keyword(kw::Impl) {
2905 return Some(true);
2906 }
2907 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2908 return None;
2910 }
2911 Some(false)
2912 });
2913 if let Some(ret) = action {
2914 return ret;
2915 }
2916 i += 1;
2917 }
2918
2919 self.is_keyword_ahead(i, &[kw::Impl])
2920 }
2921
2922 pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
2927 const ALL_QUALS: &[ExpKeywordPair] = &[
2928 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub),
2929 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen),
2930 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const),
2931 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async),
2932 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe),
2933 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe),
2934 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern),
2935 ];
2936
2937 let quals: &[_] = if check_pub {
2942 ALL_QUALS
2943 } else {
2944 &[crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe), crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern)]
2945 };
2946 self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Fn,
token_type: crate::parser::token_type::TokenType::KwFn,
}exp!(Fn), case) || quals.iter().any(|&exp| self.check_keyword_case(exp, case))
2949 && self.look_ahead(1, |t| {
2950 t.is_keyword_case(kw::Fn, case)
2952 || (
2954 (
2955 t.is_non_raw_ident_where(|i|
2956 quals.iter().any(|exp| exp.kw == i.name)
2957 && i.is_reserved()
2959 )
2960 || case == Case::Insensitive
2961 && t.is_non_raw_ident_where(|i| quals.iter().any(|exp| {
2962 exp.kw.as_str() == i.name.as_str().to_lowercase()
2963 }))
2964 )
2965 && !self.is_unsafe_foreign_mod()
2967 && !self.is_async_gen_block()
2969 && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait, kw::Impl])
2971 )
2972 })
2973 || self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern), case)
2975 && self.look_ahead(1, |t| t.can_begin_string_literal())
2979 && (self.tree_look_ahead(2, |tt| {
2980 match tt {
2981 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
2982 TokenTree::Delimited(..) => false,
2983 }
2984 }) == Some(true) ||
2985 (self.may_recover()
2988 && self.tree_look_ahead(2, |tt| {
2989 match tt {
2990 TokenTree::Token(t, _) =>
2991 ALL_QUALS.iter().any(|exp| {
2992 t.is_keyword(exp.kw)
2993 }),
2994 TokenTree::Delimited(..) => false,
2995 }
2996 }) == Some(true)
2997 && self.tree_look_ahead(3, |tt| {
2998 match tt {
2999 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
3000 TokenTree::Delimited(..) => false,
3001 }
3002 }) == Some(true)
3003 )
3004 )
3005 }
3006
3007 pub(super) fn parse_fn_front_matter(
3022 &mut self,
3023 orig_vis: &Visibility,
3024 case: Case,
3025 parsing_mode: FrontMatterParsingMode,
3026 ) -> PResult<'a, FnHeader> {
3027 let sp_start = self.token.span;
3028 let constness = self.parse_constness(case);
3029 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3030 && let Const::Yes(const_span) = constness
3031 {
3032 self.dcx().emit_err(FnPointerCannotBeConst {
3033 span: const_span,
3034 suggestion: const_span.until(self.token.span),
3035 });
3036 }
3037
3038 let async_start_sp = self.token.span;
3039 let coroutine_kind = self.parse_coroutine_kind(case);
3040 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3041 && let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind
3042 {
3043 self.dcx().emit_err(FnPointerCannotBeAsync {
3044 span: async_span,
3045 suggestion: async_span.until(self.token.span),
3046 });
3047 }
3048 let unsafe_start_sp = self.token.span;
3051 let safety = self.parse_safety(case);
3052
3053 let ext_start_sp = self.token.span;
3054 let ext = self.parse_extern(case);
3055
3056 if let Some(CoroutineKind::Async { span, .. }) = coroutine_kind {
3057 if span.is_rust_2015() {
3058 self.dcx().emit_err(errors::AsyncFnIn2015 {
3059 span,
3060 help: errors::HelpUseLatestEdition::new(),
3061 });
3062 }
3063 }
3064
3065 match coroutine_kind {
3066 Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
3067 self.psess.gated_spans.gate(sym::gen_blocks, span);
3068 }
3069 Some(CoroutineKind::Async { .. }) | None => {}
3070 }
3071
3072 if !self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Fn,
token_type: crate::parser::token_type::TokenType::KwFn,
}exp!(Fn), case) {
3073 match self.expect_one_of(&[], &[]) {
3077 Ok(Recovered::Yes(_)) => {}
3078 Ok(Recovered::No) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3079 Err(mut err) => {
3080 enum WrongKw {
3082 Duplicated(Span),
3083 Misplaced(Span),
3084 MisplacedDisallowedQualifier,
3089 }
3090
3091 let mut recover_constness = constness;
3093 let mut recover_coroutine_kind = coroutine_kind;
3094 let mut recover_safety = safety;
3095 let wrong_kw = if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) {
3098 match constness {
3099 Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
3100 Const::No => {
3101 recover_constness = Const::Yes(self.token.span);
3102 match parsing_mode {
3103 FrontMatterParsingMode::Function => {
3104 Some(WrongKw::Misplaced(async_start_sp))
3105 }
3106 FrontMatterParsingMode::FunctionPtrType => {
3107 self.dcx().emit_err(FnPointerCannotBeConst {
3108 span: self.token.span,
3109 suggestion: self
3110 .token
3111 .span
3112 .with_lo(self.prev_token.span.hi()),
3113 });
3114 Some(WrongKw::MisplacedDisallowedQualifier)
3115 }
3116 }
3117 }
3118 }
3119 } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async)) {
3120 match coroutine_kind {
3121 Some(CoroutineKind::Async { span, .. }) => {
3122 Some(WrongKw::Duplicated(span))
3123 }
3124 Some(CoroutineKind::AsyncGen { span, .. }) => {
3125 Some(WrongKw::Duplicated(span))
3126 }
3127 Some(CoroutineKind::Gen { .. }) => {
3128 recover_coroutine_kind = Some(CoroutineKind::AsyncGen {
3129 span: self.token.span,
3130 closure_id: DUMMY_NODE_ID,
3131 return_impl_trait_id: DUMMY_NODE_ID,
3132 });
3133 Some(WrongKw::Misplaced(unsafe_start_sp))
3135 }
3136 None => {
3137 recover_coroutine_kind = Some(CoroutineKind::Async {
3138 span: self.token.span,
3139 closure_id: DUMMY_NODE_ID,
3140 return_impl_trait_id: DUMMY_NODE_ID,
3141 });
3142 match parsing_mode {
3143 FrontMatterParsingMode::Function => {
3144 Some(WrongKw::Misplaced(async_start_sp))
3145 }
3146 FrontMatterParsingMode::FunctionPtrType => {
3147 self.dcx().emit_err(FnPointerCannotBeAsync {
3148 span: self.token.span,
3149 suggestion: self
3150 .token
3151 .span
3152 .with_lo(self.prev_token.span.hi()),
3153 });
3154 Some(WrongKw::MisplacedDisallowedQualifier)
3155 }
3156 }
3157 }
3158 }
3159 } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe)) {
3160 match safety {
3161 Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
3162 Safety::Safe(sp) => {
3163 recover_safety = Safety::Unsafe(self.token.span);
3164 Some(WrongKw::Misplaced(sp))
3165 }
3166 Safety::Default => {
3167 recover_safety = Safety::Unsafe(self.token.span);
3168 Some(WrongKw::Misplaced(ext_start_sp))
3169 }
3170 }
3171 } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe)) {
3172 match safety {
3173 Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
3174 Safety::Unsafe(sp) => {
3175 recover_safety = Safety::Safe(self.token.span);
3176 Some(WrongKw::Misplaced(sp))
3177 }
3178 Safety::Default => {
3179 recover_safety = Safety::Safe(self.token.span);
3180 Some(WrongKw::Misplaced(ext_start_sp))
3181 }
3182 }
3183 } else {
3184 None
3185 };
3186
3187 if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw {
3189 let original_kw = self
3190 .span_to_snippet(original_sp)
3191 .expect("Span extracted directly from keyword should always work");
3192
3193 err.span_suggestion(
3194 self.token_uninterpolated_span(),
3195 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` already used earlier, remove this one",
original_kw))
})format!("`{original_kw}` already used earlier, remove this one"),
3196 "",
3197 Applicability::MachineApplicable,
3198 )
3199 .span_note(original_sp, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` first seen here",
original_kw))
})format!("`{original_kw}` first seen here"));
3200 }
3201 else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
3203 let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
3204 if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
3205 let misplaced_qual_sp = self.token_uninterpolated_span();
3206 let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
3207
3208 err.span_suggestion(
3209 correct_pos_sp.to(misplaced_qual_sp),
3210 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` must come before `{1}`",
misplaced_qual, current_qual))
})format!("`{misplaced_qual}` must come before `{current_qual}`"),
3211 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", misplaced_qual,
current_qual))
})format!("{misplaced_qual} {current_qual}"),
3212 Applicability::MachineApplicable,
3213 ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
3214 }
3215 }
3216 else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub)) {
3218 let sp = sp_start.to(self.prev_token.span);
3219 if let Ok(snippet) = self.span_to_snippet(sp) {
3220 let current_vis = match self.parse_visibility(FollowedByType::No) {
3221 Ok(v) => v,
3222 Err(d) => {
3223 d.cancel();
3224 return Err(err);
3225 }
3226 };
3227 let vs = pprust::vis_to_string(¤t_vis);
3228 let vs = vs.trim_end();
3229
3230 if #[allow(non_exhaustive_omitted_patterns)] match orig_vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(orig_vis.kind, VisibilityKind::Inherited) {
3232 err.span_suggestion(
3233 sp_start.to(self.prev_token.span),
3234 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("visibility `{0}` must come before `{1}`",
vs, snippet))
})format!("visibility `{vs}` must come before `{snippet}`"),
3235 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", vs, snippet))
})format!("{vs} {snippet}"),
3236 Applicability::MachineApplicable,
3237 );
3238 }
3239 else {
3241 err.span_suggestion(
3242 current_vis.span,
3243 "there is already a visibility modifier, remove one",
3244 "",
3245 Applicability::MachineApplicable,
3246 )
3247 .span_note(orig_vis.span, "explicit visibility first seen here");
3248 }
3249 }
3250 }
3251
3252 if let Some(wrong_kw) = wrong_kw
3255 && self.may_recover()
3256 && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
3257 {
3258 self.bump();
3260 self.bump();
3261 if #[allow(non_exhaustive_omitted_patterns)] match wrong_kw {
WrongKw::MisplacedDisallowedQualifier => true,
_ => false,
}matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
3264 err.cancel();
3265 } else {
3266 err.emit();
3267 }
3268 return Ok(FnHeader {
3269 constness: recover_constness,
3270 safety: recover_safety,
3271 coroutine_kind: recover_coroutine_kind,
3272 ext,
3273 });
3274 }
3275
3276 return Err(err);
3277 }
3278 }
3279 }
3280
3281 Ok(FnHeader { constness, safety, coroutine_kind, ext })
3282 }
3283
3284 pub(super) fn parse_fn_decl(
3286 &mut self,
3287 fn_parse_mode: &FnParseMode,
3288 ret_allow_plus: AllowPlus,
3289 recover_return_sign: RecoverReturnSign,
3290 ) -> PResult<'a, Box<FnDecl>> {
3291 Ok(Box::new(FnDecl {
3292 inputs: self.parse_fn_params(fn_parse_mode)?,
3293 output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
3294 }))
3295 }
3296
3297 pub(super) fn parse_fn_params(
3299 &mut self,
3300 fn_parse_mode: &FnParseMode,
3301 ) -> PResult<'a, ThinVec<Param>> {
3302 let mut first_param = true;
3303 if self.token != TokenKind::OpenParen
3305 && !self.token.is_keyword(kw::For)
3307 {
3308 self.dcx()
3310 .emit_err(errors::MissingFnParams { span: self.prev_token.span.shrink_to_hi() });
3311 return Ok(ThinVec::new());
3312 }
3313
3314 let (mut params, _) = self.parse_paren_comma_seq(|p| {
3315 p.recover_vcs_conflict_marker();
3316 let snapshot = p.create_snapshot_for_diagnostic();
3317 let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| {
3318 let guar = e.emit();
3319 let lo = if let TokenKind::OpenParen = p.prev_token.kind {
3323 p.prev_token.span.shrink_to_hi()
3324 } else {
3325 p.prev_token.span
3326 };
3327 p.restore_snapshot(snapshot);
3328 p.eat_to_tokens(&[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::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
3330 Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
3332 });
3333 first_param = false;
3335 param
3336 })?;
3337 self.deduplicate_recovered_params_names(&mut params);
3339 Ok(params)
3340 }
3341
3342 pub(super) fn parse_param_general(
3347 &mut self,
3348 fn_parse_mode: &FnParseMode,
3349 first_param: bool,
3350 recover_arg_parse: bool,
3351 ) -> PResult<'a, Param> {
3352 let lo = self.token.span;
3353 let attrs = self.parse_outer_attributes()?;
3354 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3355 if let Some(mut param) = this.parse_self_param()? {
3357 param.attrs = attrs;
3358 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
3359 return Ok((res?, Trailing::No, UsePreAttrPos::No));
3360 }
3361
3362 let is_dot_dot_dot = if this.token.kind == token::DotDotDot {
3363 IsDotDotDot::Yes
3364 } else {
3365 IsDotDotDot::No
3366 };
3367 let is_name_required = (fn_parse_mode.req_name)(
3368 this.token.span.with_neighbor(this.prev_token.span).edition(),
3369 is_dot_dot_dot,
3370 );
3371 let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes {
3372 this.psess.buffer_lint(
3373 VARARGS_WITHOUT_PATTERN,
3374 this.token.span,
3375 ast::CRATE_NODE_ID,
3376 errors::VarargsWithoutPattern { span: this.token.span },
3377 );
3378 false
3379 } else {
3380 is_name_required
3381 };
3382 let (pat, ty) = if is_name_required || this.is_named_param() {
3383 {
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:3383",
"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(3383u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("parse_param_general parse_pat (is_name_required:{0})",
is_name_required) as &dyn Value))])
});
} else { ; }
};debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
3384 let (pat, colon) = this.parse_fn_param_pat_colon()?;
3385 if !colon {
3386 let mut err = this.unexpected().unwrap_err();
3387 return if let Some(ident) = this.parameter_without_type(
3388 &mut err,
3389 pat,
3390 is_name_required,
3391 first_param,
3392 fn_parse_mode,
3393 ) {
3394 let guar = err.emit();
3395 Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No))
3396 } else {
3397 Err(err)
3398 };
3399 }
3400
3401 this.eat_incorrect_doc_comment_for_param_type();
3402 (pat, this.parse_ty_for_param()?)
3403 } else {
3404 {
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:3404",
"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(3404u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("parse_param_general ident_to_pat")
as &dyn Value))])
});
} else { ; }
};debug!("parse_param_general ident_to_pat");
3405 let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
3406 this.eat_incorrect_doc_comment_for_param_type();
3407 let mut ty = this.parse_ty_for_param();
3408
3409 if let Ok(t) = &ty {
3410 if let TyKind::Path(_, Path { segments, .. }) = &t.kind
3412 && let Some(segment) = segments.last()
3413 && let Some(guar) =
3414 this.check_trailing_angle_brackets(segment, &[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)])
3415 {
3416 return Ok((
3417 dummy_arg(segment.ident, guar),
3418 Trailing::No,
3419 UsePreAttrPos::No,
3420 ));
3421 }
3422
3423 if this.token != token::Comma && this.token != token::CloseParen {
3424 ty = this.unexpected_any();
3427 }
3428 }
3429 match ty {
3430 Ok(ty) => {
3431 let pat = this.mk_pat(ty.span, PatKind::Missing);
3432 (Box::new(pat), ty)
3433 }
3434 Err(err) if this.token == token::DotDotDot => return Err(err),
3436 Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
3437 Err(err) if recover_arg_parse => {
3438 err.cancel();
3440 this.restore_snapshot(parser_snapshot_before_ty);
3441 this.recover_arg_parse()?
3442 }
3443 Err(err) => return Err(err),
3444 }
3445 };
3446
3447 let span = lo.to(this.prev_token.span);
3448
3449 Ok((
3450 Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
3451 Trailing::No,
3452 UsePreAttrPos::No,
3453 ))
3454 })
3455 }
3456
3457 fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
3459 let expect_self_ident = |this: &mut Self| match this.token.ident() {
3461 Some((ident, IdentIsRaw::No)) => {
3462 this.bump();
3463 ident
3464 }
3465 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3466 };
3467 let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime());
3469 let is_isolated_self = |this: &Self, n| {
3471 this.is_keyword_ahead(n, &[kw::SelfLower])
3472 && this.look_ahead(n + 1, |t| t != &token::PathSep)
3473 };
3474 let is_isolated_pin_const_self = |this: &Self, n| {
3476 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3477 && this.is_keyword_ahead(n + 1, &[kw::Const])
3478 && is_isolated_self(this, n + 2)
3479 };
3480 let is_isolated_mut_self =
3482 |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
3483 let is_isolated_pin_mut_self = |this: &Self, n| {
3485 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3486 && is_isolated_mut_self(this, n + 1)
3487 };
3488 let parse_self_possibly_typed = |this: &mut Self, m| {
3490 let eself_ident = expect_self_ident(this);
3491 let eself_hi = this.prev_token.span;
3492 let eself = if this.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) {
3493 SelfKind::Explicit(this.parse_ty()?, m)
3494 } else {
3495 SelfKind::Value(m)
3496 };
3497 Ok((eself, eself_ident, eself_hi))
3498 };
3499 let expect_self_ident_not_typed =
3500 |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
3501 let eself_ident = expect_self_ident(this);
3502
3503 if this.may_recover() && this.eat_noexpect(&token::Colon) {
3505 let snap = this.create_snapshot_for_diagnostic();
3506 match this.parse_ty() {
3507 Ok(ty) => {
3508 this.dcx().emit_err(errors::IncorrectTypeOnSelf {
3509 span: ty.span,
3510 move_self_modifier: errors::MoveSelfModifier {
3511 removal_span: modifier_span,
3512 insertion_span: ty.span.shrink_to_lo(),
3513 modifier: modifier.to_ref_suggestion(),
3514 },
3515 });
3516 }
3517 Err(diag) => {
3518 diag.cancel();
3519 this.restore_snapshot(snap);
3520 }
3521 }
3522 }
3523 eself_ident
3524 };
3525 let recover_self_ptr = |this: &mut Self| {
3527 this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
3528
3529 Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
3530 };
3531
3532 let eself_lo = self.token.span;
3536 let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
3537 token::And => {
3538 let has_lifetime = is_lifetime(self, 1);
3539 let skip_lifetime_count = has_lifetime as usize;
3540 let eself = if is_isolated_self(self, skip_lifetime_count + 1) {
3541 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3544 SelfKind::Region(lifetime, Mutability::Not)
3545 } else if is_isolated_mut_self(self, skip_lifetime_count + 1) {
3546 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3549 self.bump(); SelfKind::Region(lifetime, Mutability::Mut)
3551 } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) {
3552 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3555 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3556 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Not)
3559 } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) {
3560 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3563 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3564 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Mut)
3567 } else {
3568 return Ok(None);
3570 };
3571 let hi = self.token.span;
3572 let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
3573 (eself, self_ident, hi)
3574 }
3575 token::Star if is_isolated_self(self, 1) => {
3577 self.bump();
3578 recover_self_ptr(self)?
3579 }
3580 token::Star
3582 if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
3583 {
3584 self.bump();
3585 self.bump();
3586 recover_self_ptr(self)?
3587 }
3588 token::Ident(..) if is_isolated_self(self, 0) => {
3590 parse_self_possibly_typed(self, Mutability::Not)?
3591 }
3592 token::Ident(..) if is_isolated_mut_self(self, 0) => {
3594 self.bump();
3595 parse_self_possibly_typed(self, Mutability::Mut)?
3596 }
3597 _ => return Ok(None),
3598 };
3599
3600 let eself = respan(eself_lo.to(eself_hi), eself);
3601 Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
3602 }
3603
3604 fn is_named_param(&self) -> bool {
3605 let offset = match &self.token.kind {
3606 token::OpenInvisible(origin) => match origin {
3607 InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
3608 return self.check_noexpect_past_close_delim(&token::Colon);
3609 }
3610 _ => 0,
3611 },
3612 token::And | token::AndAnd => 1,
3613 _ if self.token.is_keyword(kw::Mut) => 1,
3614 _ => 0,
3615 };
3616
3617 self.look_ahead(offset, |t| t.is_ident())
3618 && self.look_ahead(offset + 1, |t| t == &token::Colon)
3619 }
3620
3621 fn recover_self_param(&mut self) -> bool {
3622 #[allow(non_exhaustive_omitted_patterns)] match self.parse_outer_attributes().and_then(|_|
self.parse_self_param()).map_err(|e| e.cancel()) {
Ok(Some(_)) => true,
_ => false,
}matches!(
3623 self.parse_outer_attributes()
3624 .and_then(|_| self.parse_self_param())
3625 .map_err(|e| e.cancel()),
3626 Ok(Some(_))
3627 )
3628 }
3629
3630 fn try_recover_const_missing_semi(
3638 &mut self,
3639 rhs: &ConstItemRhsKind,
3640 const_span: Span,
3641 ) -> Option<Box<Expr>> {
3642 if self.token == TokenKind::Semi {
3643 return None;
3644 }
3645 let ConstItemRhsKind::Body { rhs: Some(rhs) } = rhs else {
3646 return None;
3647 };
3648 if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
3649 return None;
3650 }
3651 if let Some((span, guar)) =
3652 self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
3653 {
3654 self.fn_body_missing_semi_guar = Some(guar);
3655 Some(self.mk_expr(span, ExprKind::Err(guar)))
3656 } else {
3657 None
3658 }
3659 }
3660}
3661
3662enum IsMacroRulesItem {
3663 Yes { has_bang: bool },
3664 No,
3665}
3666
3667#[derive(#[automatically_derived]
impl ::core::marker::Copy for FrontMatterParsingMode { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FrontMatterParsingMode {
#[inline]
fn clone(&self) -> FrontMatterParsingMode { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for FrontMatterParsingMode {
#[inline]
fn eq(&self, other: &FrontMatterParsingMode) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FrontMatterParsingMode {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
3668pub(super) enum FrontMatterParsingMode {
3669 Function,
3671 FunctionPtrType,
3674}