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::{
27 self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField,
28 UseDoubleColonSuggestion, UseRegularStructSuggestion,
29};
30use crate::exp;
31
32impl<'a> Parser<'a> {
33 pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
35 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))?;
36 Ok(ast::Crate { attrs, items, spans, id: DUMMY_NODE_ID, is_placeholder: false })
37 }
38
39 fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
41 let safety = self.parse_safety(Case::Sensitive);
42 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mod,
token_type: crate::parser::token_type::TokenType::KwMod,
}exp!(Mod))?;
43 let ident = self.parse_ident()?;
44 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)) {
45 ModKind::Unloaded
46 } else {
47 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
48 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))?;
49 attrs.extend(inner_attrs);
50 ModKind::Loaded(items, Inline::Yes, inner_span)
51 };
52 Ok(ItemKind::Mod(safety, ident, mod_kind))
53 }
54
55 pub fn parse_mod(
60 &mut self,
61 term: ExpTokenPair,
62 ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
63 let lo = self.token.span;
64 let attrs = self.parse_inner_attributes()?;
65
66 let post_attr_lo = self.token.span;
67 let mut items: ThinVec<Box<_>> = ThinVec::new();
68
69 loop {
72 while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else {
74 break;
75 };
76 items.push(item);
77 }
78
79 if !self.eat(term) {
80 let token_str = super::token_descr(&self.token);
81 if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
82 let is_let = self.token.is_keyword(kw::Let);
83 let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
84 let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);
85
86 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected item, found {0}",
token_str))
})format!("expected item, found {token_str}");
87 let mut err = self.dcx().struct_span_err(self.token.span, msg);
88
89 let label = if is_let {
90 "`let` cannot be used for global variables"
91 } else {
92 "expected item"
93 };
94 err.span_label(self.token.span, label);
95
96 if is_let {
97 if is_let_mut {
98 err.help("consider using `static` and a `Mutex` instead of `let mut`");
99 } else if let_has_ident {
100 err.span_suggestion_short(
101 self.token.span,
102 "consider using `static` or `const` instead of `let`",
103 "static",
104 Applicability::MaybeIncorrect,
105 );
106 } else {
107 err.help("consider using `static` or `const` instead of `let`");
108 }
109 }
110 err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
111 return Err(err);
112 }
113 }
114
115 let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo());
116 let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };
117 Ok((attrs, items, mod_spans))
118 }
119}
120
121enum ReuseKind {
122 Path,
123 Impl,
124}
125
126impl<'a> Parser<'a> {
127 pub fn parse_item(
128 &mut self,
129 force_collect: ForceCollect,
130 allow_const_block_items: AllowConstBlockItems,
131 ) -> PResult<'a, Option<Box<Item>>> {
132 let fn_parse_mode =
133 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
134 self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items)
135 .map(|i| i.map(Box::new))
136 }
137
138 fn parse_item_(
139 &mut self,
140 fn_parse_mode: FnParseMode,
141 force_collect: ForceCollect,
142 const_block_items_allowed: AllowConstBlockItems,
143 ) -> PResult<'a, Option<Item>> {
144 self.recover_vcs_conflict_marker();
145 let attrs = self.parse_outer_attributes()?;
146 self.recover_vcs_conflict_marker();
147 self.parse_item_common(
148 attrs,
149 true,
150 false,
151 fn_parse_mode,
152 force_collect,
153 const_block_items_allowed,
154 )
155 }
156
157 pub(super) fn parse_item_common(
158 &mut self,
159 attrs: AttrWrapper,
160 mac_allowed: bool,
161 attrs_allowed: bool,
162 fn_parse_mode: FnParseMode,
163 force_collect: ForceCollect,
164 allow_const_block_items: AllowConstBlockItems,
165 ) -> PResult<'a, Option<Item>> {
166 if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| {
167 this.parse_item(ForceCollect::Yes, allow_const_block_items)
168 }) {
169 let mut item = item.expect("an actual item");
170 attrs.prepend_to_nt_inner(&mut item.attrs);
171 return Ok(Some(*item));
172 }
173
174 self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {
175 let lo = this.token.span;
176 let vis = this.parse_visibility(FollowedByType::No)?;
177 let mut def = this.parse_defaultness();
178 let kind = this.parse_item_kind(
179 &mut attrs,
180 mac_allowed,
181 allow_const_block_items,
182 lo,
183 &vis,
184 &mut def,
185 fn_parse_mode,
186 Case::Sensitive,
187 )?;
188 if let Some(kind) = kind {
189 this.error_on_unconsumed_default(def, &kind);
190 let span = lo.to(this.prev_token.span);
191 let id = DUMMY_NODE_ID;
192 let item = Item { attrs, id, kind, vis, span, tokens: None };
193 return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
194 }
195
196 if !#[allow(non_exhaustive_omitted_patterns)] match vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(vis.kind, VisibilityKind::Inherited) {
198 let vis_str = pprust::vis_to_string(&vis).trim_end().to_string();
199 let mut err = this.dcx().create_err(errors::VisibilityNotFollowedByItem {
200 span: vis.span,
201 vis: vis_str,
202 });
203 if let Some((ident, _)) = this.token.ident()
204 && !ident.is_used_keyword()
205 && let Some((similar_kw, is_incorrect_case)) = ident
206 .name
207 .find_similar(&rustc_span::symbol::used_keywords(|| ident.span.edition()))
208 {
209 err.subdiagnostic(errors::MisspelledKw {
210 similar_kw: similar_kw.to_string(),
211 span: ident.span,
212 is_incorrect_case,
213 });
214 }
215 err.emit();
216 }
217
218 if let Defaultness::Default(span) = def {
219 this.dcx().emit_err(errors::DefaultNotFollowedByItem { span });
220 } else if let Defaultness::Final(span) = def {
221 this.dcx().emit_err(errors::FinalNotFollowedByItem { span });
222 }
223
224 if !attrs_allowed {
225 this.recover_attrs_no_item(&attrs)?;
226 }
227 Ok((None, Trailing::No, UsePreAttrPos::No))
228 })
229 }
230
231 fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
233 match def {
234 Defaultness::Default(span) => {
235 self.dcx().emit_err(errors::InappropriateDefault {
236 span,
237 article: kind.article(),
238 descr: kind.descr(),
239 });
240 }
241 Defaultness::Final(span) => {
242 self.dcx().emit_err(errors::InappropriateFinal {
243 span,
244 article: kind.article(),
245 descr: kind.descr(),
246 });
247 }
248 Defaultness::Implicit => (),
249 }
250 }
251
252 fn parse_item_kind(
254 &mut self,
255 attrs: &mut AttrVec,
256 macros_allowed: bool,
257 allow_const_block_items: AllowConstBlockItems,
258 lo: Span,
259 vis: &Visibility,
260 def: &mut Defaultness,
261 fn_parse_mode: FnParseMode,
262 case: Case,
263 ) -> PResult<'a, Option<ItemKind>> {
264 let check_pub = def == &Defaultness::Implicit;
265 let mut def_ = || mem::replace(def, Defaultness::Implicit);
266
267 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) {
268 self.parse_use_item()?
269 } else if self.check_fn_front_matter(check_pub, case) {
270 let defaultness = def_();
272 if let Defaultness::Default(span) = defaultness {
273 self.psess.gated_spans.gate(sym::min_specialization, span);
277 self.psess.gated_spans.ungate_last(sym::specialization, span);
278 }
279 let (ident, sig, generics, contract, body) =
280 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
281 ItemKind::Fn(Box::new(Fn {
282 defaultness,
283 ident,
284 sig,
285 generics,
286 contract,
287 body,
288 define_opaque: None,
289 eii_impls: ThinVec::new(),
290 }))
291 } 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) {
292 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) {
293 self.parse_item_extern_crate()?
295 } else {
296 self.parse_item_foreign_mod(attrs, Safety::Default)?
298 }
299 } else if self.is_unsafe_foreign_mod() {
300 let safety = self.parse_safety(Case::Sensitive);
302 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern))?;
303 self.parse_item_foreign_mod(attrs, safety)?
304 } else if let Some(safety) = self.parse_global_static_front_matter(case) {
305 let mutability = self.parse_mutability();
307 self.parse_static_item(safety, mutability)?
308 } 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() {
309 self.parse_item_trait(attrs, lo)?
311 } else if self.check_impl_frontmatter(0) {
312 self.parse_item_impl(attrs, def_(), false)?
314 } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
315 allow_const_block_items
316 && self.check_inline_const(0)
317 {
318 if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
320 {
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:320",
"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(320u32),
::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);
321 };
322 ItemKind::ConstBlock(self.parse_const_block_item()?)
323 } else if let Const::Yes(const_span) = self.parse_constness(case) {
324 self.recover_const_mut(const_span);
326 self.recover_missing_kw_before_item()?;
327 let (ident, generics, ty, rhs_kind) = self.parse_const_item(false, const_span)?;
328 ItemKind::Const(Box::new(ConstItem {
329 defaultness: def_(),
330 ident,
331 generics,
332 ty,
333 rhs_kind,
334 define_opaque: None,
335 }))
336 } else if let Some(kind) = self.is_reuse_item() {
337 self.parse_item_delegation(attrs, def_(), kind)?
338 } 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)
339 || 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])
340 {
341 self.parse_item_mod(attrs)?
343 } 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) {
344 if let Const::Yes(const_span) = self.parse_constness(case) {
345 self.recover_const_mut(const_span);
347 self.recover_missing_kw_before_item()?;
348 let (ident, generics, ty, rhs_kind) = self.parse_const_item(true, const_span)?;
349 self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span));
352 ItemKind::Const(Box::new(ConstItem {
353 defaultness: def_(),
354 ident,
355 generics,
356 ty,
357 rhs_kind,
358 define_opaque: None,
359 }))
360 } else {
361 self.parse_type_alias(def_())?
363 }
364 } 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) {
365 self.parse_item_enum()?
367 } 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) {
368 self.parse_item_struct()?
370 } else if self.is_kw_followed_by_ident(kw::Union) {
371 self.bump(); self.parse_item_union()?
374 } else if self.is_builtin() {
375 return self.parse_item_builtin();
377 } 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) {
378 self.parse_item_decl_macro(lo)?
380 } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
381 self.parse_item_macro_rules(vis, has_bang)?
383 } else if self.isnt_macro_invocation()
384 && (self.token.is_ident_named(sym::import)
385 || self.token.is_ident_named(sym::using)
386 || self.token.is_ident_named(sym::include)
387 || self.token.is_ident_named(sym::require))
388 {
389 return self.recover_import_as_use();
390 } else if self.isnt_macro_invocation() && vis.kind.is_pub() {
391 self.recover_missing_kw_before_item()?;
392 return Ok(None);
393 } else if self.isnt_macro_invocation() && case == Case::Sensitive {
394 _ = def_;
395
396 return self.parse_item_kind(
398 attrs,
399 macros_allowed,
400 allow_const_block_items,
401 lo,
402 vis,
403 def,
404 fn_parse_mode,
405 Case::Insensitive,
406 );
407 } else if macros_allowed && self.check_path() {
408 if self.isnt_macro_invocation() {
409 self.recover_missing_kw_before_item()?;
410 }
411 ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
413 } else {
414 return Ok(None);
415 };
416 Ok(Some(info))
417 }
418
419 fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
420 let span = self.token.span;
421 let token_name = super::token_descr(&self.token);
422 let snapshot = self.create_snapshot_for_diagnostic();
423 self.bump();
424 match self.parse_use_item() {
425 Ok(u) => {
426 self.dcx().emit_err(errors::RecoverImportAsUse { span, token_name });
427 Ok(Some(u))
428 }
429 Err(e) => {
430 e.cancel();
431 self.restore_snapshot(snapshot);
432 Ok(None)
433 }
434 }
435 }
436
437 fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
438 let tree = self.parse_use_tree()?;
439 if let Err(mut e) = self.expect_semi() {
440 match tree.kind {
441 UseTreeKind::Glob(_) => {
442 e.note("the wildcard token must be last on the path");
443 }
444 UseTreeKind::Nested { .. } => {
445 e.note("glob-like brace syntax must be last on the path");
446 }
447 _ => (),
448 }
449 return Err(e);
450 }
451 Ok(ItemKind::Use(tree))
452 }
453
454 pub(super) fn is_path_start_item(&mut self) -> bool {
456 self.is_kw_followed_by_ident(kw::Union) || self.is_reuse_item().is_some() || self.check_trait_front_matter() || self.is_async_fn() || #[allow(non_exhaustive_omitted_patterns)] match self.is_macro_rules_item() {
IsMacroRulesItem::Yes { .. } => true,
_ => false,
}matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) }
462
463 fn is_reuse_item(&mut self) -> Option<ReuseKind> {
464 if !self.token.is_keyword(kw::Reuse) {
465 return None;
466 }
467
468 if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
470 Some(ReuseKind::Path)
471 } else if self.check_impl_frontmatter(1) {
472 Some(ReuseKind::Impl)
473 } else {
474 None
475 }
476 }
477
478 fn isnt_macro_invocation(&mut self) -> bool {
480 self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
481 }
482
483 fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
486 let is_pub = self.prev_token.is_keyword(kw::Pub);
487 let is_const = self.prev_token.is_keyword(kw::Const);
488 let ident_span = self.token.span;
489 let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };
490 let insert_span = ident_span.shrink_to_lo();
491
492 let ident = if self.token.is_ident()
493 && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
494 && self.look_ahead(1, |t| {
495 #[allow(non_exhaustive_omitted_patterns)] match t.kind {
token::Lt | token::OpenBrace | token::OpenParen => true,
_ => false,
}matches!(t.kind, token::Lt | token::OpenBrace | token::OpenParen)
496 }) {
497 self.parse_ident_common(true).unwrap()
498 } else {
499 return Ok(());
500 };
501
502 let mut found_generics = false;
503 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Lt,
token_type: crate::parser::token_type::TokenType::Lt,
}exp!(Lt)) {
504 found_generics = true;
505 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Gt,
token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)]);
506 self.bump(); }
508
509 let err = if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
510 if self.look_ahead(1, |t| *t == token::CloseBrace) {
512 Some(errors::MissingKeywordForItemDefinition::EnumOrStruct { span })
514 } else if self.look_ahead(2, |t| *t == token::Colon)
515 || self.look_ahead(3, |t| *t == token::Colon)
516 {
517 Some(errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident })
519 } else {
520 Some(errors::MissingKeywordForItemDefinition::Enum { span, insert_span, ident })
521 }
522 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
523 self.bump(); let is_method = self.recover_self_param();
526
527 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);
528
529 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)) {
530 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)]);
531 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);
533 if is_method {
534 errors::MissingKeywordForItemDefinition::Method { span, insert_span, ident }
535 } else {
536 errors::MissingKeywordForItemDefinition::Function { span, insert_span, ident }
537 }
538 } 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)) {
539 errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
540 } else {
541 errors::MissingKeywordForItemDefinition::Ambiguous {
542 span,
543 subdiag: if found_generics {
544 None
545 } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
546 Some(errors::AmbiguousMissingKwForItemSub::SuggestMacro {
547 span: ident_span,
548 snippet,
549 })
550 } else {
551 Some(errors::AmbiguousMissingKwForItemSub::HelpMacro)
552 },
553 }
554 };
555 Some(err)
556 } else if found_generics {
557 Some(errors::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
558 } else {
559 None
560 };
561
562 if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
563 }
564
565 fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
566 Ok(None)
568 }
569
570 fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
572 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() {
575 Ok(args) => {
577 self.eat_semi_for_macro_if_needed(&args, Some(&path));
578 self.complain_if_pub_macro(vis, false);
579 Ok(MacCall { path, args })
580 }
581
582 Err(mut err) => {
583 if self.token.is_ident()
585 && let [segment] = path.segments.as_slice()
586 && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
587 {
588 err.span_suggestion(
589 path.span,
590 "perhaps you meant to define a macro",
591 "macro_rules",
592 Applicability::MachineApplicable,
593 );
594 }
595 Err(err)
596 }
597 }
598 }
599
600 fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
602 let ([start @ end] | [start, .., end]) = attrs else {
603 return Ok(());
604 };
605 let msg = if end.is_doc_comment() {
606 "expected item after doc comment"
607 } else {
608 "expected item after attributes"
609 };
610 let mut err = self.dcx().struct_span_err(end.span, msg);
611 if end.is_doc_comment() {
612 err.span_label(end.span, "this doc comment doesn't document anything");
613 } else if self.token == TokenKind::Semi {
614 err.span_suggestion_verbose(
615 self.token.span,
616 "consider removing this semicolon",
617 "",
618 Applicability::MaybeIncorrect,
619 );
620 }
621 if let [.., penultimate, _] = attrs {
622 err.span_label(start.span.to(penultimate.span), "other attributes here");
623 }
624 Err(err)
625 }
626
627 fn is_async_fn(&self) -> bool {
628 self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
629 }
630
631 fn parse_polarity(&mut self) -> ast::ImplPolarity {
632 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()) {
634 self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
635 self.bump(); ast::ImplPolarity::Negative(self.prev_token.span)
637 } else {
638 ast::ImplPolarity::Positive
639 }
640 }
641
642 fn parse_item_impl(
657 &mut self,
658 attrs: &mut AttrVec,
659 defaultness: Defaultness,
660 is_reuse: bool,
661 ) -> PResult<'a, ItemKind> {
662 let mut constness = self.parse_constness(Case::Sensitive);
663 let safety = self.parse_safety(Case::Sensitive);
664 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
665
666 let mut generics = if self.choose_generics_over_qpath(0) {
668 self.parse_generics()?
669 } else {
670 let mut generics = Generics::default();
671 generics.span = self.prev_token.span.shrink_to_hi();
674 generics
675 };
676
677 if let Const::No = constness {
678 constness = self.parse_constness(Case::Sensitive);
680 }
681
682 if let Const::Yes(span) = constness {
683 self.psess.gated_spans.gate(sym::const_trait_impl, span);
684 }
685
686 if (self.token_uninterpolated_span().at_least_rust_2018()
688 && self.token.is_keyword(kw::Async))
689 || self.is_kw_followed_by_ident(kw::Async)
690 {
691 self.bump();
692 self.dcx().emit_err(errors::AsyncImpl { span: self.prev_token.span });
693 }
694
695 let polarity = self.parse_polarity();
696
697 let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
699 {
700 let span = self.prev_token.span.between(self.token.span);
701 return Err(self.dcx().create_err(errors::MissingTraitInTraitImpl {
702 span,
703 for_span: span.to(self.token.span),
704 }));
705 } else {
706 self.parse_ty_with_generics_recovery(&generics)?
707 };
708
709 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));
711 let missing_for_span = self.prev_token.span.between(self.token.span);
712
713 let ty_second = if self.token == token::DotDot {
714 self.bump(); Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
721 } else if has_for || self.token.can_begin_type() {
722 Some(self.parse_ty()?)
723 } else {
724 None
725 };
726
727 generics.where_clause = self.parse_where_clause()?;
728
729 let impl_items = if is_reuse {
730 Default::default()
731 } else {
732 self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
733 };
734
735 let (of_trait, self_ty) = match ty_second {
736 Some(ty_second) => {
737 if !has_for {
739 self.dcx().emit_err(errors::MissingForInTraitImpl { span: missing_for_span });
740 }
741
742 let ty_first = *ty_first;
743 let path = match ty_first.kind {
744 TyKind::Path(None, path) => path,
746 other => {
747 if let TyKind::ImplTrait(_, bounds) = other
748 && let [bound] = bounds.as_slice()
749 && let GenericBound::Trait(poly_trait_ref) = bound
750 {
751 let extra_impl_kw = ty_first.span.until(bound.span());
755 self.dcx().emit_err(errors::ExtraImplKeywordInTraitImpl {
756 extra_impl_kw,
757 impl_trait_span: ty_first.span,
758 });
759 poly_trait_ref.trait_ref.path.clone()
760 } else {
761 return Err(self.dcx().create_err(
762 errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span },
763 ));
764 }
765 }
766 };
767 let trait_ref = TraitRef { path, ref_id: ty_first.id };
768
769 let of_trait =
770 Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
771 (of_trait, ty_second)
772 }
773 None => {
774 let self_ty = ty_first;
775 let error = |modifier, modifier_name, modifier_span| {
776 self.dcx().create_err(errors::TraitImplModifierInInherentImpl {
777 span: self_ty.span,
778 modifier,
779 modifier_name,
780 modifier_span,
781 self_ty: self_ty.span,
782 })
783 };
784
785 if let Safety::Unsafe(span) = safety {
786 error("unsafe", "unsafe", span).with_code(E0197).emit();
787 }
788 if let ImplPolarity::Negative(span) = polarity {
789 error("!", "negative", span).emit();
790 }
791 if let Defaultness::Default(def_span) = defaultness {
792 error("default", "default", def_span).emit();
793 }
794 if let Const::Yes(span) = constness {
795 self.psess.gated_spans.gate(sym::const_trait_impl, span);
796 }
797 (None, self_ty)
798 }
799 };
800
801 Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
802 }
803
804 fn parse_item_delegation(
805 &mut self,
806 attrs: &mut AttrVec,
807 defaultness: Defaultness,
808 kind: ReuseKind,
809 ) -> PResult<'a, ItemKind> {
810 let span = self.token.span;
811 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Reuse,
token_type: crate::parser::token_type::TokenType::KwReuse,
}exp!(Reuse))?;
812
813 let item_kind = match kind {
814 ReuseKind::Path => self.parse_path_like_delegation(),
815 ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
816 }?;
817
818 self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
819
820 Ok(item_kind)
821 }
822
823 fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
824 Ok(if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
825 Some(self.parse_block()?)
826 } else {
827 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))?;
828 None
829 })
830 }
831
832 fn parse_impl_delegation(
833 &mut self,
834 span: Span,
835 attrs: &mut AttrVec,
836 defaultness: Defaultness,
837 ) -> PResult<'a, ItemKind> {
838 let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
839 let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
840
841 let until_expr_span = span.to(self.prev_token.span);
842
843 let Some(of_trait) = of_trait else {
844 return Err(self
845 .dcx()
846 .create_err(errors::ImplReuseInherentImpl { span: until_expr_span }));
847 };
848
849 let body = self.parse_delegation_body()?;
850 let whole_reuse_span = span.to(self.prev_token.span);
851
852 items.push(Box::new(AssocItem {
853 id: DUMMY_NODE_ID,
854 attrs: Default::default(),
855 span: whole_reuse_span,
856 tokens: None,
857 vis: Visibility {
858 kind: VisibilityKind::Inherited,
859 span: whole_reuse_span,
860 tokens: None,
861 },
862 kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
863 qself: None,
864 prefix: of_trait.trait_ref.path.clone(),
865 suffixes: DelegationSuffixes::Glob(whole_reuse_span),
866 body,
867 })),
868 }));
869
870 Ok(impl_item)
871 }
872
873 fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
874 let (qself, path) = if self.eat_lt() {
875 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
876 (Some(qself), path)
877 } else {
878 (None, self.parse_path(PathStyle::Expr)?)
879 };
880
881 let rename = |this: &mut Self| {
882 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 })
883 };
884
885 Ok(if self.eat_path_sep() {
886 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)) {
887 DelegationSuffixes::Glob(self.prev_token.span)
888 } else {
889 let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
890 DelegationSuffixes::List(
891 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,
892 )
893 };
894
895 ItemKind::DelegationMac(Box::new(DelegationMac {
896 qself,
897 prefix: path,
898 suffixes,
899 body: self.parse_delegation_body()?,
900 }))
901 } else {
902 let rename = rename(self)?;
903 let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
904
905 ItemKind::Delegation(Box::new(Delegation {
906 id: DUMMY_NODE_ID,
907 qself,
908 path,
909 ident,
910 rename,
911 body: self.parse_delegation_body()?,
912 from_glob: false,
913 }))
914 })
915 }
916
917 fn parse_item_list<T>(
918 &mut self,
919 attrs: &mut AttrVec,
920 mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
921 ) -> PResult<'a, ThinVec<T>> {
922 let open_brace_span = self.token.span;
923
924 if self.token == TokenKind::Semi {
926 self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
927 self.bump();
928 return Ok(ThinVec::new());
929 }
930
931 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
932 attrs.extend(self.parse_inner_attributes()?);
933
934 let mut items = ThinVec::new();
935 while !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)) {
936 if self.recover_doc_comment_before_brace() {
937 continue;
938 }
939 self.recover_vcs_conflict_marker();
940 match parse_item(self) {
941 Ok(None) => {
942 let mut is_unnecessary_semicolon = !items.is_empty()
943 && self
961 .span_to_snippet(self.prev_token.span)
962 .is_ok_and(|snippet| snippet == "}")
963 && self.token == token::Semi;
964 let mut semicolon_span = self.token.span;
965 if !is_unnecessary_semicolon {
966 is_unnecessary_semicolon =
968 self.token == token::OpenBrace && self.prev_token == token::Semi;
969 semicolon_span = self.prev_token.span;
970 }
971 let non_item_span = self.token.span;
973 let is_let = self.token.is_keyword(kw::Let);
974
975 let mut err =
976 self.dcx().struct_span_err(non_item_span, "non-item in item list");
977 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);
978 if is_let {
979 err.span_suggestion_verbose(
980 non_item_span,
981 "consider using `const` instead of `let` for associated const",
982 "const",
983 Applicability::MachineApplicable,
984 );
985 } else {
986 err.span_label(open_brace_span, "item list starts here")
987 .span_label(non_item_span, "non-item starts here")
988 .span_label(self.prev_token.span, "item list ends here");
989 }
990 if is_unnecessary_semicolon {
991 err.span_suggestion(
992 semicolon_span,
993 "consider removing this semicolon",
994 "",
995 Applicability::MaybeIncorrect,
996 );
997 }
998 err.emit();
999 break;
1000 }
1001 Ok(Some(item)) => items.extend(item),
1002 Err(err) => {
1003 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);
1004 err.with_span_label(
1005 open_brace_span,
1006 "while parsing this item list starting here",
1007 )
1008 .with_span_label(self.prev_token.span, "the item list ends here")
1009 .emit();
1010 break;
1011 }
1012 }
1013 }
1014 Ok(items)
1015 }
1016
1017 fn recover_doc_comment_before_brace(&mut self) -> bool {
1019 if let token::DocComment(..) = self.token.kind {
1020 if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
1021 {
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!(
1023 self.dcx(),
1024 self.token.span,
1025 E0584,
1026 "found a documentation comment that doesn't document anything",
1027 )
1028 .with_span_label(self.token.span, "this doc comment doesn't document anything")
1029 .with_help(
1030 "doc comments must come before what they document, if a comment was \
1031 intended use `//`",
1032 )
1033 .emit();
1034 self.bump();
1035 return true;
1036 }
1037 }
1038 false
1039 }
1040
1041 fn parse_defaultness(&mut self) -> Defaultness {
1043 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))
1047 && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
1048 {
1049 self.psess.gated_spans.gate(sym::specialization, self.token.span);
1050 self.bump(); Defaultness::Default(self.prev_token_uninterpolated_span())
1052 } 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)) {
1053 self.psess.gated_spans.gate(sym::final_associated_functions, self.prev_token.span);
1054 Defaultness::Final(self.prev_token_uninterpolated_span())
1055 } else {
1056 Defaultness::Implicit
1057 }
1058 }
1059
1060 fn check_trait_front_matter(&mut self) -> bool {
1062 const SUFFIXES: &[&[Symbol]] = &[
1063 &[kw::Trait],
1064 &[kw::Auto, kw::Trait],
1065 &[kw::Unsafe, kw::Trait],
1066 &[kw::Unsafe, kw::Auto, kw::Trait],
1067 &[kw::Const, kw::Trait],
1068 &[kw::Const, kw::Auto, kw::Trait],
1069 &[kw::Const, kw::Unsafe, kw::Trait],
1070 &[kw::Const, kw::Unsafe, kw::Auto, kw::Trait],
1071 ];
1072 if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl)) && self.look_ahead(1, |t| t == &token::OpenParen) {
1074 if self.is_keyword_ahead(2, &[kw::In]) {
1076 return true;
1077 }
1078 if self.is_keyword_ahead(2, &[kw::Crate, kw::SelfLower, kw::Super])
1080 && self.look_ahead(3, |t| t == &token::CloseParen)
1081 && SUFFIXES.iter().any(|suffix| {
1082 suffix.iter().enumerate().all(|(i, kw)| self.is_keyword_ahead(i + 4, &[*kw]))
1083 })
1084 {
1085 return true;
1086 }
1087 SUFFIXES.iter().any(|suffix| {
1089 suffix.iter().enumerate().all(|(i, kw)| {
1090 self.tree_look_ahead(i + 2, |t| {
1091 if let TokenTree::Token(token, _) = t {
1092 token.is_keyword(*kw)
1093 } else {
1094 false
1095 }
1096 })
1097 .unwrap_or(false)
1098 })
1099 })
1100 } else {
1101 SUFFIXES.iter().any(|suffix| {
1102 suffix.iter().enumerate().all(|(i, kw)| {
1103 if i == 0 {
1105 match *kw {
1106 kw::Const => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)),
1107 kw::Unsafe => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe)),
1108 kw::Auto => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Auto,
token_type: crate::parser::token_type::TokenType::KwAuto,
}exp!(Auto)),
1109 kw::Trait => self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait)),
1110 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1111 }
1112 } else {
1113 self.is_keyword_ahead(i, &[*kw])
1114 }
1115 })
1116 })
1117 }
1118 }
1119
1120 fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
1122 let impl_restriction = self.parse_impl_restriction()?;
1123 let constness = self.parse_constness(Case::Sensitive);
1124 if let Const::Yes(span) = constness {
1125 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1126 }
1127 let safety = self.parse_safety(Case::Sensitive);
1128 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)) {
1130 self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
1131 IsAuto::Yes
1132 } else {
1133 IsAuto::No
1134 };
1135
1136 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait))?;
1137 let ident = self.parse_ident()?;
1138 let mut generics = self.parse_generics()?;
1139
1140 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));
1142 let span_at_colon = self.prev_token.span;
1143 let bounds = if had_colon { self.parse_generic_bounds()? } else { Vec::new() };
1144
1145 let span_before_eq = self.prev_token.span;
1146 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1147 if had_colon {
1149 let span = span_at_colon.to(span_before_eq);
1150 self.dcx().emit_err(errors::BoundsNotAllowedOnTraitAliases { span });
1151 }
1152
1153 let bounds = self.parse_generic_bounds()?;
1154 generics.where_clause = self.parse_where_clause()?;
1155 self.expect_semi()?;
1156
1157 let whole_span = lo.to(self.prev_token.span);
1158 if is_auto == IsAuto::Yes {
1159 self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span });
1160 }
1161 if let Safety::Unsafe(_) = safety {
1162 self.dcx().emit_err(errors::TraitAliasCannotBeUnsafe { span: whole_span });
1163 }
1164 if let RestrictionKind::Restricted { .. } = impl_restriction.kind {
1165 self.dcx().emit_err(errors::TraitAliasCannotBeImplRestricted { span: whole_span });
1166 }
1167
1168 self.psess.gated_spans.gate(sym::trait_alias, whole_span);
1169
1170 Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
1171 } else {
1172 generics.where_clause = self.parse_where_clause()?;
1174 let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
1175 Ok(ItemKind::Trait(Box::new(Trait {
1176 impl_restriction,
1177 constness,
1178 is_auto,
1179 safety,
1180 ident,
1181 generics,
1182 bounds,
1183 items,
1184 })))
1185 }
1186 }
1187
1188 pub fn parse_impl_item(
1189 &mut self,
1190 force_collect: ForceCollect,
1191 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1192 let fn_parse_mode =
1193 FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
1194 self.parse_assoc_item(fn_parse_mode, force_collect)
1195 }
1196
1197 pub fn parse_trait_item(
1198 &mut self,
1199 force_collect: ForceCollect,
1200 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1201 let fn_parse_mode = FnParseMode {
1202 req_name: |edition, _| edition >= Edition::Edition2018,
1203 context: FnContext::Trait,
1204 req_body: false,
1205 };
1206 self.parse_assoc_item(fn_parse_mode, force_collect)
1207 }
1208
1209 fn parse_assoc_item(
1211 &mut self,
1212 fn_parse_mode: FnParseMode,
1213 force_collect: ForceCollect,
1214 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1215 Ok(self
1216 .parse_item_(
1217 fn_parse_mode,
1218 force_collect,
1219 AllowConstBlockItems::DoesNotMatter, )?
1221 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1222 let kind = match AssocItemKind::try_from(kind) {
1223 Ok(kind) => kind,
1224 Err(kind) => match kind {
1225 ItemKind::Static(StaticItem {
1226 ident,
1227 ty,
1228 safety: _,
1229 mutability: _,
1230 expr,
1231 define_opaque,
1232 eii_impls: _,
1233 }) => {
1234 self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
1235 AssocItemKind::Const(Box::new(ConstItem {
1236 defaultness: Defaultness::Implicit,
1237 ident,
1238 generics: Generics::default(),
1239 ty,
1240 rhs_kind: ConstItemRhsKind::Body { rhs: expr },
1241 define_opaque,
1242 }))
1243 }
1244 _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
1245 },
1246 };
1247 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1248 }))
1249 }
1250
1251 fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
1257 let ident = self.parse_ident()?;
1258 let mut generics = self.parse_generics()?;
1259
1260 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() };
1262 generics.where_clause = self.parse_where_clause()?;
1263
1264 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 };
1265
1266 let after_where_clause = self.parse_where_clause()?;
1267
1268 self.expect_semi()?;
1269
1270 Ok(ItemKind::TyAlias(Box::new(TyAlias {
1271 defaultness,
1272 ident,
1273 generics,
1274 after_where_clause,
1275 bounds,
1276 ty,
1277 })))
1278 }
1279
1280 fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
1290 let lo = self.token.span;
1291
1292 let mut prefix =
1293 ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo(), tokens: None };
1294 let kind =
1295 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() {
1296 let mod_sep_ctxt = self.token.span.ctxt();
1298 if self.eat_path_sep() {
1299 prefix
1300 .segments
1301 .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
1302 }
1303
1304 self.parse_use_tree_glob_or_nested()?
1305 } else {
1306 prefix = self.parse_path(PathStyle::Mod)?;
1308
1309 if self.eat_path_sep() {
1310 self.parse_use_tree_glob_or_nested()?
1311 } else {
1312 while self.eat_noexpect(&token::Colon) {
1314 self.dcx()
1315 .emit_err(errors::SingleColonImportPath { span: self.prev_token.span });
1316
1317 self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
1319 prefix.span = lo.to(self.prev_token.span);
1320 }
1321
1322 UseTreeKind::Simple(self.parse_rename()?)
1323 }
1324 };
1325
1326 Ok(UseTree { prefix, kind })
1327 }
1328
1329 fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
1331 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
1332 UseTreeKind::Glob(self.prev_token.span)
1333 } else {
1334 let lo = self.token.span;
1335 UseTreeKind::Nested {
1336 items: self.parse_use_tree_list()?,
1337 span: lo.to(self.prev_token.span),
1338 }
1339 })
1340 }
1341
1342 fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
1348 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| {
1349 p.recover_vcs_conflict_marker();
1350 Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
1351 })
1352 .map(|(r, _)| r)
1353 }
1354
1355 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1356 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)) {
1357 self.parse_ident_or_underscore().map(Some)
1358 } else {
1359 Ok(None)
1360 }
1361 }
1362
1363 fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
1364 match self.token.ident() {
1365 Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
1366 self.bump();
1367 Ok(ident)
1368 }
1369 _ => self.parse_ident(),
1370 }
1371 }
1372
1373 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1382 let orig_ident = self.parse_crate_name_with_dashes()?;
1384 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1385 (Some(orig_ident.name), rename)
1386 } else {
1387 (None, orig_ident)
1388 };
1389 self.expect_semi()?;
1390 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1391 }
1392
1393 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1394 let ident = if self.token.is_keyword(kw::SelfLower) {
1395 self.parse_path_segment_ident()
1396 } else {
1397 self.parse_ident()
1398 }?;
1399
1400 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1401 if self.token != dash.tok {
1402 return Ok(ident);
1403 }
1404
1405 let mut dashes = ::alloc::vec::Vec::new()vec![];
1407 let mut idents = ::alloc::vec::Vec::new()vec![];
1408 while self.eat(dash) {
1409 dashes.push(self.prev_token.span);
1410 idents.push(self.parse_ident()?);
1411 }
1412
1413 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1414 let mut fixed_name = ident.name.to_string();
1415 for part in idents {
1416 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1417 }
1418
1419 self.dcx().emit_err(errors::ExternCrateNameWithDashes {
1420 span: fixed_name_sp,
1421 sugg: errors::ExternCrateNameWithDashesSugg { dashes },
1422 });
1423
1424 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1425 }
1426
1427 fn parse_item_foreign_mod(
1438 &mut self,
1439 attrs: &mut AttrVec,
1440 mut safety: Safety,
1441 ) -> PResult<'a, ItemKind> {
1442 let extern_span = self.prev_token_uninterpolated_span();
1443 let abi = self.parse_abi(); if safety == Safety::Default
1446 && self.token.is_keyword(kw::Unsafe)
1447 && self.look_ahead(1, |t| *t == token::OpenBrace)
1448 {
1449 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();
1450 safety = Safety::Unsafe(self.token.span);
1451 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));
1452 }
1453 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1454 extern_span,
1455 safety,
1456 abi,
1457 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1458 }))
1459 }
1460
1461 pub fn parse_foreign_item(
1463 &mut self,
1464 force_collect: ForceCollect,
1465 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1466 let fn_parse_mode = FnParseMode {
1467 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1468 context: FnContext::Free,
1469 req_body: false,
1470 };
1471 Ok(self
1472 .parse_item_(
1473 fn_parse_mode,
1474 force_collect,
1475 AllowConstBlockItems::DoesNotMatter, )?
1477 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1478 let kind = match ForeignItemKind::try_from(kind) {
1479 Ok(kind) => kind,
1480 Err(kind) => match kind {
1481 ItemKind::Const(ConstItem { ident, ty, rhs_kind, .. }) => {
1482 let const_span = Some(span.with_hi(ident.span.lo()))
1483 .filter(|span| span.can_be_used_for_suggestions());
1484 self.dcx().emit_err(errors::ExternItemCannotBeConst {
1485 ident_span: ident.span,
1486 const_span,
1487 });
1488 ForeignItemKind::Static(Box::new(StaticItem {
1489 ident,
1490 ty,
1491 mutability: Mutability::Not,
1492 expr: match rhs_kind {
1493 ConstItemRhsKind::Body { rhs } => rhs,
1494 ConstItemRhsKind::TypeConst { rhs: Some(anon) } => {
1495 Some(anon.value)
1496 }
1497 ConstItemRhsKind::TypeConst { rhs: None } => None,
1498 },
1499 safety: Safety::Default,
1500 define_opaque: None,
1501 eii_impls: ThinVec::default(),
1502 }))
1503 }
1504 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1505 },
1506 };
1507 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1508 }))
1509 }
1510
1511 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1512 let span = self.psess.source_map().guess_head_span(span);
1514 let descr = kind.descr();
1515 let help = match kind {
1516 ItemKind::DelegationMac(DelegationMac {
1517 suffixes: DelegationSuffixes::Glob(_),
1518 ..
1519 }) => false,
1520 _ => true,
1521 };
1522 self.dcx().emit_err(errors::BadItemKind { span, descr, ctx, help });
1523 None
1524 }
1525
1526 fn is_use_closure(&self) -> bool {
1527 if self.token.is_keyword(kw::Use) {
1528 self.look_ahead(1, |token| {
1530 let dist =
1532 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1533
1534 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))
1535 })
1536 } else {
1537 false
1538 }
1539 }
1540
1541 fn is_unsafe_foreign_mod(&self) -> bool {
1542 if !self.token.is_keyword(kw::Unsafe) {
1544 return false;
1545 }
1546 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1548 return false;
1549 }
1550
1551 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1553
1554 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, _)))
1559 == Some(true)
1560 }
1561
1562 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1563 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) {
1564 !self.look_ahead(1, |token| {
1566 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1567 return true;
1568 }
1569 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1570 })
1571 } else {
1572 (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)
1574 || 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))
1575 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1576 };
1577
1578 if is_global_static {
1579 let safety = self.parse_safety(case);
1580 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);
1581 Some(safety)
1582 } else {
1583 None
1584 }
1585 }
1586
1587 fn recover_const_mut(&mut self, const_span: Span) {
1589 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)) {
1590 let span = self.prev_token.span;
1591 self.dcx()
1592 .emit_err(errors::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1593 } 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)) {
1594 let span = self.prev_token.span;
1595 self.dcx().emit_err(errors::ConstLetMutuallyExclusive { span: const_span.to(span) });
1596 }
1597 }
1598
1599 fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
1600 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1601 let const_span = self.prev_token.span;
1602 self.psess.gated_spans.gate(sym::const_block_items, const_span);
1603 let block = self.parse_block()?;
1604 Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
1605 }
1606
1607 fn parse_static_item(
1614 &mut self,
1615 safety: Safety,
1616 mutability: Mutability,
1617 ) -> PResult<'a, ItemKind> {
1618 let ident = self.parse_ident()?;
1619
1620 if self.token == TokenKind::Lt && self.may_recover() {
1621 let generics = self.parse_generics()?;
1622 self.dcx().emit_err(errors::StaticWithGenerics { span: generics.span });
1623 }
1624
1625 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))) {
1628 (true, false) => self.parse_ty()?,
1629 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1632 };
1633
1634 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 };
1635
1636 self.expect_semi()?;
1637
1638 let item = StaticItem {
1639 ident,
1640 ty,
1641 safety,
1642 mutability,
1643 expr,
1644 define_opaque: None,
1645 eii_impls: ThinVec::default(),
1646 };
1647 Ok(ItemKind::Static(Box::new(item)))
1648 }
1649
1650 fn parse_const_item(
1659 &mut self,
1660 const_arg: bool,
1661 const_span: Span,
1662 ) -> PResult<'a, (Ident, Generics, Box<Ty>, ConstItemRhsKind)> {
1663 let ident = self.parse_ident_or_underscore()?;
1664
1665 let mut generics = self.parse_generics()?;
1666
1667 if !generics.span.is_empty() {
1670 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1671 }
1672
1673 let ty = match (
1676 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1677 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)),
1678 ) {
1679 (true, false) => self.parse_ty()?,
1680 (colon, _) => self.recover_missing_global_item_type(colon, None),
1682 };
1683
1684 let before_where_clause =
1687 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1688
1689 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) {
1690 (true, true) => ConstItemRhsKind::TypeConst {
1691 rhs: Some(self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?),
1692 },
1693 (true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) },
1694 (false, true) => ConstItemRhsKind::TypeConst { rhs: None },
1695 (false, false) => ConstItemRhsKind::Body { rhs: None },
1696 };
1697
1698 let after_where_clause = self.parse_where_clause()?;
1699
1700 if before_where_clause.has_where_token
1704 && let Some(rhs_span) = rhs.span()
1705 {
1706 self.dcx().emit_err(errors::WhereClauseBeforeConstBody {
1707 span: before_where_clause.span,
1708 name: ident.span,
1709 body: rhs_span,
1710 sugg: if !after_where_clause.has_where_token {
1711 self.psess.source_map().span_to_snippet(rhs_span).ok().map(|body_s| {
1712 errors::WhereClauseBeforeConstBodySugg {
1713 left: before_where_clause.span.shrink_to_lo(),
1714 snippet: body_s,
1715 right: before_where_clause.span.shrink_to_hi().to(rhs_span),
1716 }
1717 })
1718 } else {
1719 None
1722 },
1723 });
1724 }
1725
1726 let mut predicates = before_where_clause.predicates;
1733 predicates.extend(after_where_clause.predicates);
1734 let where_clause = WhereClause {
1735 has_where_token: before_where_clause.has_where_token
1736 || after_where_clause.has_where_token,
1737 predicates,
1738 span: if after_where_clause.has_where_token {
1739 after_where_clause.span
1740 } else {
1741 before_where_clause.span
1742 },
1743 };
1744
1745 if where_clause.has_where_token {
1746 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1747 }
1748
1749 generics.where_clause = where_clause;
1750
1751 if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
1752 return Ok((ident, generics, ty, ConstItemRhsKind::Body { rhs: Some(rhs) }));
1753 }
1754 self.expect_semi()?;
1755
1756 Ok((ident, generics, ty, rhs))
1757 }
1758
1759 fn recover_missing_global_item_type(
1762 &mut self,
1763 colon_present: bool,
1764 m: Option<Mutability>,
1765 ) -> Box<Ty> {
1766 let kind = match m {
1769 Some(Mutability::Mut) => "static mut",
1770 Some(Mutability::Not) => "static",
1771 None => "const",
1772 };
1773
1774 let colon = match colon_present {
1775 true => "",
1776 false => ":",
1777 };
1778
1779 let span = self.prev_token.span.shrink_to_hi();
1780 let err = self.dcx().create_err(errors::MissingConstType { span, colon, kind });
1781 err.stash(span, StashKey::ItemNoType);
1782
1783 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None })
1786 }
1787
1788 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1790 if self.token.is_keyword(kw::Struct) {
1791 let span = self.prev_token.span.to(self.token.span);
1792 let err = errors::EnumStructMutuallyExclusive { span };
1793 if self.look_ahead(1, |t| t.is_ident()) {
1794 self.bump();
1795 self.dcx().emit_err(err);
1796 } else {
1797 return Err(self.dcx().create_err(err));
1798 }
1799 }
1800
1801 let prev_span = self.prev_token.span;
1802 let ident = self.parse_ident()?;
1803 let mut generics = self.parse_generics()?;
1804 generics.where_clause = self.parse_where_clause()?;
1805
1806 let (variants, _) = if self.token == TokenKind::Semi {
1808 self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
1809 self.bump();
1810 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1811 } else {
1812 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| {
1813 p.parse_enum_variant(ident.span)
1814 })
1815 .map_err(|mut err| {
1816 err.span_label(ident.span, "while parsing this enum");
1817 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1819 let snapshot = self.create_snapshot_for_diagnostic();
1820 self.bump();
1821 match self.parse_ty() {
1822 Ok(_) => {
1823 err.span_suggestion_verbose(
1824 prev_span,
1825 "perhaps you meant to use `struct` here",
1826 "struct",
1827 Applicability::MaybeIncorrect,
1828 );
1829 }
1830 Err(e) => {
1831 e.cancel();
1832 }
1833 }
1834 self.restore_snapshot(snapshot);
1835 }
1836 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1837 self.bump(); err
1839 })?
1840 };
1841
1842 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1843 Ok(ItemKind::Enum(ident, generics, enum_definition))
1844 }
1845
1846 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1847 self.recover_vcs_conflict_marker();
1848 let variant_attrs = self.parse_outer_attributes()?;
1849 self.recover_vcs_conflict_marker();
1850 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1851 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1852 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1853 let vlo = this.token.span;
1854
1855 let vis = this.parse_visibility(FollowedByType::No)?;
1856 if !this.recover_nested_adt_item(kw::Enum)? {
1857 return Ok((None, Trailing::No, UsePreAttrPos::No));
1858 }
1859 let ident = this.parse_field_ident("enum", vlo)?;
1860
1861 if this.token == token::Bang {
1862 if let Err(err) = this.unexpected() {
1863 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();
1864 }
1865
1866 this.bump();
1867 this.parse_delim_args()?;
1868
1869 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1870 }
1871
1872 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)) {
1873 let (fields, recovered) =
1875 match this.parse_record_struct_body("struct", ident.span, false) {
1876 Ok((fields, recovered)) => (fields, recovered),
1877 Err(mut err) => {
1878 if this.token == token::Colon {
1879 return Err(err);
1881 }
1882 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1883 this.bump(); err.span_label(span, "while parsing this enum");
1885 err.help(help);
1886 let guar = err.emit();
1887 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1888 }
1889 };
1890 VariantData::Struct { fields, recovered }
1891 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1892 let body = match this.parse_tuple_struct_body() {
1893 Ok(body) => body,
1894 Err(mut err) => {
1895 if this.token == token::Colon {
1896 return Err(err);
1898 }
1899 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
1900 this.bump(); err.span_label(span, "while parsing this enum");
1902 err.help(help);
1903 err.emit();
1904 ::thin_vec::ThinVec::new()thin_vec![]
1905 }
1906 };
1907 VariantData::Tuple(body, DUMMY_NODE_ID)
1908 } else {
1909 VariantData::Unit(DUMMY_NODE_ID)
1910 };
1911
1912 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)) {
1913 Some(this.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?)
1914 } else {
1915 None
1916 };
1917
1918 let vr = ast::Variant {
1919 ident,
1920 vis,
1921 id: DUMMY_NODE_ID,
1922 attrs: variant_attrs,
1923 data: struct_def,
1924 disr_expr,
1925 span: vlo.to(this.prev_token.span),
1926 is_placeholder: false,
1927 };
1928
1929 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
1930 })
1931 .map_err(|mut err| {
1932 err.help(help);
1933 err
1934 })
1935 }
1936
1937 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
1939 let ident = self.parse_ident()?;
1940
1941 let mut generics = self.parse_generics()?;
1942
1943 let vdata = if self.token.is_keyword(kw::Where) {
1958 let tuple_struct_body;
1959 (generics.where_clause, tuple_struct_body) =
1960 self.parse_struct_where_clause(ident, generics.span)?;
1961
1962 if let Some(body) = tuple_struct_body {
1963 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
1965 self.expect_semi()?;
1966 body
1967 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1968 VariantData::Unit(DUMMY_NODE_ID)
1970 } else {
1971 let (fields, recovered) = self.parse_record_struct_body(
1973 "struct",
1974 ident.span,
1975 generics.where_clause.has_where_token,
1976 )?;
1977 VariantData::Struct { fields, recovered }
1978 }
1979 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1981 VariantData::Unit(DUMMY_NODE_ID)
1982 } else if self.token == token::OpenBrace {
1984 let (fields, recovered) = self.parse_record_struct_body(
1985 "struct",
1986 ident.span,
1987 generics.where_clause.has_where_token,
1988 )?;
1989 VariantData::Struct { fields, recovered }
1990 } else if self.token == token::OpenParen {
1992 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
1993 generics.where_clause = self.parse_where_clause()?;
1994 self.expect_semi()?;
1995 body
1996 } else {
1997 let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
1998 return Err(self.dcx().create_err(err));
1999 };
2000
2001 Ok(ItemKind::Struct(ident, generics, vdata))
2002 }
2003
2004 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
2006 let ident = self.parse_ident()?;
2007
2008 let mut generics = self.parse_generics()?;
2009
2010 let vdata = if self.token.is_keyword(kw::Where) {
2011 generics.where_clause = self.parse_where_clause()?;
2012 let (fields, recovered) = self.parse_record_struct_body(
2013 "union",
2014 ident.span,
2015 generics.where_clause.has_where_token,
2016 )?;
2017 VariantData::Struct { fields, recovered }
2018 } else if self.token == token::OpenBrace {
2019 let (fields, recovered) = self.parse_record_struct_body(
2020 "union",
2021 ident.span,
2022 generics.where_clause.has_where_token,
2023 )?;
2024 VariantData::Struct { fields, recovered }
2025 } else {
2026 let token_str = super::token_descr(&self.token);
2027 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}");
2028 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2029 err.span_label(self.token.span, "expected `where` or `{` after union name");
2030 return Err(err);
2031 };
2032
2033 Ok(ItemKind::Union(ident, generics, vdata))
2034 }
2035
2036 pub(crate) fn parse_record_struct_body(
2041 &mut self,
2042 adt_ty: &str,
2043 ident_span: Span,
2044 parsed_where: bool,
2045 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
2046 let mut fields = ThinVec::new();
2047 let mut recovered = Recovered::No;
2048 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2049 while self.token != token::CloseBrace {
2050 match self.parse_field_def(adt_ty, ident_span) {
2051 Ok(field) => {
2052 fields.push(field);
2053 }
2054 Err(mut err) => {
2055 self.consume_block(
2056 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
2057 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
2058 ConsumeClosingDelim::No,
2059 );
2060 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}"));
2061 let guar = err.emit();
2062 recovered = Recovered::Yes(guar);
2063 break;
2064 }
2065 }
2066 }
2067 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
2068 } else {
2069 let token_str = super::token_descr(&self.token);
2070 let where_str = if parsed_where { "" } else { "`where`, or " };
2071 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}");
2072 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2073 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",));
2074 return Err(err);
2075 }
2076
2077 Ok((fields, recovered))
2078 }
2079
2080 fn parse_unsafe_field(&mut self) -> Safety {
2081 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)) {
2083 let span = self.prev_token.span;
2084 self.psess.gated_spans.gate(sym::unsafe_fields, span);
2085 Safety::Unsafe(span)
2086 } else {
2087 Safety::Default
2088 }
2089 }
2090 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
2093 let openparen_span = self.token.span;
2094 let mut encountered_colon = false;
2095 self.parse_paren_comma_seq(|p| {
2096 let attrs = p.parse_outer_attributes()?;
2097 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
2098 let mut snapshot = None;
2099 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
2100 snapshot = Some(p.create_snapshot_for_diagnostic());
2104 }
2105 let lo = p.token.span;
2106 let vis = match p.parse_visibility(FollowedByType::Yes) {
2107 Ok(vis) => vis,
2108 Err(err) => {
2109 if let Some(ref mut snapshot) = snapshot {
2110 snapshot.recover_vcs_conflict_marker();
2111 }
2112 return Err(err);
2113 }
2114 };
2115 let mut_restriction = p.parse_mut_restriction()?;
2116 encountered_colon |=
2117 p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
2118 let ty = match p.parse_ty() {
2121 Ok(ty) => ty,
2122 Err(err) => {
2123 if let Some(ref mut snapshot) = snapshot {
2124 snapshot.recover_vcs_conflict_marker();
2125 }
2126 return Err(err);
2127 }
2128 };
2129 let mut default = None;
2130 if p.token == token::Eq {
2131 let mut snapshot = p.create_snapshot_for_diagnostic();
2132 snapshot.bump();
2133 match snapshot.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst) {
2134 Ok(const_expr) => {
2135 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2136 p.psess.gated_spans.gate(sym::default_field_values, sp);
2137 p.restore_snapshot(snapshot);
2138 default = Some(const_expr);
2139 }
2140 Err(err) => {
2141 err.cancel();
2142 }
2143 }
2144 }
2145
2146 Ok((
2147 FieldDef {
2148 span: lo.to(ty.span),
2149 vis,
2150 mut_restriction,
2151 safety: Safety::Default,
2152 ident: None,
2153 id: DUMMY_NODE_ID,
2154 ty,
2155 default,
2156 attrs,
2157 is_placeholder: false,
2158 },
2159 Trailing::from(p.token == token::Comma),
2160 UsePreAttrPos::No,
2161 ))
2162 })
2163 })
2164 .map(|(r, _)| r)
2165 .map_err(|mut error| {
2166 if encountered_colon {
2167 error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
2168 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
2169 self.bump();
2170 error.subdiagnostic(UseRegularStructSuggestion {
2171 open: openparen_span,
2172 close: self.prev_token.span,
2173 semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
2174 });
2175 }
2176 error
2177 })
2178 }
2179
2180 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2182 self.recover_vcs_conflict_marker();
2183 let attrs = self.parse_outer_attributes()?;
2184 self.recover_vcs_conflict_marker();
2185 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2186 let lo = this.token.span;
2187 let vis = this.parse_visibility(FollowedByType::No)?;
2188 let mut_restriction = this.parse_mut_restriction()?;
2189 let safety = this.parse_unsafe_field();
2190 this.parse_single_struct_field(
2191 adt_ty,
2192 lo,
2193 vis,
2194 mut_restriction,
2195 safety,
2196 attrs,
2197 ident_span,
2198 )
2199 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2200 })
2201 }
2202
2203 fn parse_single_struct_field(
2205 &mut self,
2206 adt_ty: &str,
2207 lo: Span,
2208 vis: Visibility,
2209 mut_restriction: MutRestriction,
2210 safety: Safety,
2211 attrs: AttrVec,
2212 ident_span: Span,
2213 ) -> PResult<'a, FieldDef> {
2214 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, mut_restriction, safety, attrs)?;
2215 match self.token.kind {
2216 token::Comma => {
2217 self.bump();
2218 }
2219 token::Semi => {
2220 self.bump();
2221 let sp = self.prev_token.span;
2222 let mut err =
2223 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 `,`"));
2224 err.span_suggestion_short(
2225 sp,
2226 "replace `;` with `,`",
2227 ",",
2228 Applicability::MachineApplicable,
2229 );
2230 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}"));
2231 err.emit();
2232 }
2233 token::CloseBrace => {}
2234 token::DocComment(..) => {
2235 let previous_span = self.prev_token.span;
2236 let mut err = errors::DocCommentDoesNotDocumentAnything {
2237 span: self.token.span,
2238 missing_comma: None,
2239 };
2240 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 {
2242 self.dcx().emit_err(err);
2243 } else {
2244 let sp = previous_span.shrink_to_hi();
2245 err.missing_comma = Some(sp);
2246 return Err(self.dcx().create_err(err));
2247 }
2248 }
2249 _ => {
2250 let sp = self.prev_token.span.shrink_to_hi();
2251 let msg =
2252 ::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));
2253
2254 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2256 && let Some(last_segment) = segments.last()
2257 {
2258 let guar = self.check_trailing_angle_brackets(
2259 last_segment,
2260 &[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)],
2261 );
2262 if let Some(_guar) = guar {
2263 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2266
2267 return Ok(a_var);
2270 }
2271 }
2272
2273 let mut err = self.dcx().struct_span_err(sp, msg);
2274
2275 if self.token.is_ident()
2276 || (self.token == TokenKind::Pound
2277 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2278 {
2279 err.span_suggestion(
2282 sp,
2283 "try adding a comma",
2284 ",",
2285 Applicability::MachineApplicable,
2286 );
2287 err.emit();
2288 } else {
2289 return Err(err);
2290 }
2291 }
2292 }
2293 Ok(a_var)
2294 }
2295
2296 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2297 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)) {
2298 let sm = self.psess.source_map();
2299 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2300 let semi_typo = self.token == token::Semi
2301 && self.look_ahead(1, |t| {
2302 t.is_path_start()
2303 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2306 (Ok(l), Ok(r)) => l.line == r.line,
2307 _ => true,
2308 }
2309 });
2310 if eq_typo || semi_typo {
2311 self.bump();
2312 err.with_span_suggestion_short(
2314 self.prev_token.span,
2315 "field names and their types are separated with `:`",
2316 ":",
2317 Applicability::MachineApplicable,
2318 )
2319 .emit();
2320 } else {
2321 return Err(err);
2322 }
2323 }
2324 Ok(())
2325 }
2326
2327 fn parse_name_and_ty(
2329 &mut self,
2330 adt_ty: &str,
2331 lo: Span,
2332 vis: Visibility,
2333 mut_restriction: MutRestriction,
2334 safety: Safety,
2335 attrs: AttrVec,
2336 ) -> PResult<'a, FieldDef> {
2337 let name = self.parse_field_ident(adt_ty, lo)?;
2338 if self.token == token::Bang {
2339 if let Err(mut err) = self.unexpected() {
2340 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2342 return Err(err);
2343 }
2344 }
2345 self.expect_field_ty_separator()?;
2346 let ty = self.parse_ty()?;
2347 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2348 self.dcx()
2349 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2350 .with_span_suggestion_verbose(
2351 self.token.span,
2352 "write a path separator here",
2353 "::",
2354 Applicability::MaybeIncorrect,
2355 )
2356 .emit();
2357 }
2358 let default = if self.token == token::Eq {
2359 self.bump();
2360 let const_expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
2361 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2362 self.psess.gated_spans.gate(sym::default_field_values, sp);
2363 Some(const_expr)
2364 } else {
2365 None
2366 };
2367 Ok(FieldDef {
2368 span: lo.to(self.prev_token.span),
2369 ident: Some(name),
2370 vis,
2371 safety,
2372 mut_restriction,
2373 id: DUMMY_NODE_ID,
2374 ty,
2375 default,
2376 attrs,
2377 is_placeholder: false,
2378 })
2379 }
2380
2381 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2384 let (ident, is_raw) = self.ident_or_err(true)?;
2385 if is_raw == IdentIsRaw::No && ident.is_reserved() {
2386 let snapshot = self.create_snapshot_for_diagnostic();
2387 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2388 let inherited_vis =
2389 Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
2390 let fn_parse_mode =
2392 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2393 match self.parse_fn(
2394 &mut AttrVec::new(),
2395 fn_parse_mode,
2396 lo,
2397 &inherited_vis,
2398 Case::Insensitive,
2399 ) {
2400 Ok(_) => {
2401 self.dcx().struct_span_err(
2402 lo.to(self.prev_token.span),
2403 ::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"),
2404 )
2405 .with_help(
2406 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2407 )
2408 .with_help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information")
2409 }
2410 Err(err) => {
2411 err.cancel();
2412 self.restore_snapshot(snapshot);
2413 self.expected_ident_found_err()
2414 }
2415 }
2416 } 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)) {
2417 match self.parse_item_struct() {
2418 Ok(item) => {
2419 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2420 self.dcx()
2421 .struct_span_err(
2422 lo.with_hi(ident.span.hi()),
2423 ::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"),
2424 )
2425 .with_help(
2426 "consider creating a new `struct` definition instead of nesting",
2427 )
2428 }
2429 Err(err) => {
2430 err.cancel();
2431 self.restore_snapshot(snapshot);
2432 self.expected_ident_found_err()
2433 }
2434 }
2435 } else {
2436 let mut err = self.expected_ident_found_err();
2437 if self.eat_keyword_noexpect(kw::Let)
2438 && let removal_span = self.prev_token.span.until(self.token.span)
2439 && let Ok(ident) = self
2440 .parse_ident_common(false)
2441 .map_err(|err| err.cancel())
2443 && self.token == TokenKind::Colon
2444 {
2445 err.span_suggestion(
2446 removal_span,
2447 "remove this `let` keyword",
2448 String::new(),
2449 Applicability::MachineApplicable,
2450 );
2451 err.note("the `let` keyword is not allowed in `struct` fields");
2452 err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
2453 err.emit();
2454 return Ok(ident);
2455 } else {
2456 self.restore_snapshot(snapshot);
2457 }
2458 err
2459 };
2460 return Err(err);
2461 }
2462 self.bump();
2463 Ok(ident)
2464 }
2465
2466 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2474 let ident = self.parse_ident()?;
2475 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)) {
2476 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)) {
2478 let params = self.parse_token_tree(); let pspan = params.span();
2480 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2481 self.unexpected()?;
2482 }
2483 let body = self.parse_token_tree(); let bspan = body.span();
2486 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]);
2488 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2489 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2490 } else {
2491 self.unexpected_any()?
2492 };
2493
2494 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2495 Ok(ItemKind::MacroDef(
2496 ident,
2497 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2498 ))
2499 }
2500
2501 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2503 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)) {
2504 let macro_rules_span = self.token.span;
2505
2506 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2507 return IsMacroRulesItem::Yes { has_bang: true };
2508 } else if self.look_ahead(1, |t| t.is_ident()) {
2509 self.dcx().emit_err(errors::MacroRulesMissingBang {
2511 span: macro_rules_span,
2512 hi: macro_rules_span.shrink_to_hi(),
2513 });
2514
2515 return IsMacroRulesItem::Yes { has_bang: false };
2516 }
2517 }
2518
2519 IsMacroRulesItem::No
2520 }
2521
2522 fn parse_item_macro_rules(
2524 &mut self,
2525 vis: &Visibility,
2526 has_bang: bool,
2527 ) -> PResult<'a, ItemKind> {
2528 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 {
2531 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2533 let ident = self.parse_ident()?;
2534
2535 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2536 let span = self.prev_token.span;
2538 self.dcx().emit_err(errors::MacroNameRemoveBang { span });
2539 }
2540
2541 let body = self.parse_delim_args()?;
2542 self.eat_semi_for_macro_if_needed(&body, None);
2543 self.complain_if_pub_macro(vis, true);
2544
2545 Ok(ItemKind::MacroDef(
2546 ident,
2547 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2548 ))
2549 }
2550
2551 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2554 if let VisibilityKind::Inherited = vis.kind {
2555 return;
2556 }
2557
2558 let vstr = pprust::vis_to_string(vis);
2559 let vstr = vstr.trim_end();
2560 if macro_rules {
2561 self.dcx().emit_err(errors::MacroRulesVisibility { span: vis.span, vis: vstr });
2562 } else {
2563 self.dcx().emit_err(errors::MacroInvocationVisibility { span: vis.span, vis: vstr });
2564 }
2565 }
2566
2567 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
2568 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)) {
2569 self.report_invalid_macro_expansion_item(args, path);
2570 }
2571 }
2572
2573 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
2574 let span = args.dspan.entire();
2575 let mut err = self.dcx().struct_span_err(
2576 span,
2577 "macros that expand to items must be delimited with braces or followed by a semicolon",
2578 );
2579 if !span.from_expansion() {
2582 let DelimSpan { open, close } = args.dspan;
2583 if let Some(path) = path
2586 && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2587 && args.delim == Delimiter::Parenthesis
2588 {
2589 let replace =
2590 if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2591 err.multipart_suggestion(
2592 "to define a macro, remove the parentheses around the macro name",
2593 ::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())],
2594 Applicability::MachineApplicable,
2595 );
2596 } else {
2597 err.multipart_suggestion(
2598 "change the delimiters to curly braces",
2599 ::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())],
2600 Applicability::MaybeIncorrect,
2601 );
2602 err.span_suggestion(
2603 span.with_neighbor(self.token.span).shrink_to_hi(),
2604 "add a semicolon",
2605 ';',
2606 Applicability::MaybeIncorrect,
2607 );
2608 }
2609 }
2610 err.emit();
2611 }
2612
2613 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2616 if (self.token.is_keyword(kw::Enum)
2617 || self.token.is_keyword(kw::Struct)
2618 || self.token.is_keyword(kw::Union))
2619 && self.look_ahead(1, |t| t.is_ident())
2620 {
2621 let kw_token = self.token;
2622 let kw_str = pprust::token_to_string(&kw_token);
2623 let item = self.parse_item(
2624 ForceCollect::No,
2625 AllowConstBlockItems::DoesNotMatter, )?;
2627 let mut item = item.unwrap().span;
2628 if self.token == token::Comma {
2629 item = item.to(self.token.span);
2630 }
2631 self.dcx().emit_err(errors::NestedAdt {
2632 span: kw_token.span,
2633 item,
2634 kw_str,
2635 keyword: keyword.as_str(),
2636 });
2637 return Ok(false);
2639 }
2640 Ok(true)
2641 }
2642}
2643
2644type ReqName = fn(Edition, IsDotDotDot) -> bool;
2653
2654#[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)]
2655pub(crate) enum IsDotDotDot {
2656 Yes,
2657 No,
2658}
2659
2660#[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)]
2668pub(crate) struct FnParseMode {
2669 pub(super) req_name: ReqName,
2695 pub(super) context: FnContext,
2698 pub(super) req_body: bool,
2717}
2718
2719#[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)]
2722pub(crate) enum FnContext {
2723 Free,
2725 Trait,
2727 Impl,
2729}
2730
2731impl<'a> Parser<'a> {
2733 fn parse_fn(
2735 &mut self,
2736 attrs: &mut AttrVec,
2737 fn_parse_mode: FnParseMode,
2738 sig_lo: Span,
2739 vis: &Visibility,
2740 case: Case,
2741 ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
2742 let fn_span = self.token.span;
2743 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)
2747 {
2748 Ok(decl) => decl,
2749 Err(old_err) => {
2750 if self.token.is_keyword(kw::For) {
2752 old_err.cancel();
2753 return Err(self.dcx().create_err(errors::FnTypoWithImpl { fn_span }));
2754 } else {
2755 return Err(old_err);
2756 }
2757 }
2758 };
2759
2760 let fn_params_end = self.prev_token.span.shrink_to_hi();
2763
2764 let contract = self.parse_contract()?;
2765
2766 generics.where_clause = self.parse_where_clause()?; let fn_params_end =
2770 if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
2771
2772 let mut sig_hi = self.prev_token.span;
2773 let body =
2775 self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
2776 let fn_sig_span = sig_lo.to(sig_hi);
2777 Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
2778 }
2779
2780 fn error_fn_body_not_found(
2782 &mut self,
2783 ident_span: Span,
2784 req_body: bool,
2785 fn_params_end: Option<Span>,
2786 ) -> PResult<'a, ErrorGuaranteed> {
2787 let expected: &[_] =
2788 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)] };
2789 match self.expected_one_of_not_found(&[], expected) {
2790 Ok(error_guaranteed) => Ok(error_guaranteed),
2791 Err(mut err) => {
2792 if self.token == token::CloseBrace {
2793 err.span_label(ident_span, "while parsing this `fn`");
2796 Ok(err.emit())
2797 } else if self.token == token::RArrow
2798 && let Some(fn_params_end) = fn_params_end
2799 {
2800 let fn_trait_span =
2806 [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
2807 if self.prev_token.is_ident_named(symbol) {
2808 Some(self.prev_token.span)
2809 } else {
2810 None
2811 }
2812 });
2813
2814 let arrow_span = self.token.span;
2819 let ty_span = match self.parse_ret_ty(
2820 AllowPlus::Yes,
2821 RecoverQPath::Yes,
2822 RecoverReturnSign::Yes,
2823 ) {
2824 Ok(ty_span) => ty_span.span().shrink_to_hi(),
2825 Err(parse_error) => {
2826 parse_error.cancel();
2827 return Err(err);
2828 }
2829 };
2830 let ret_ty_span = arrow_span.to(ty_span);
2831
2832 if let Some(fn_trait_span) = fn_trait_span {
2833 err.subdiagnostic(errors::FnTraitMissingParen { span: fn_trait_span });
2836 } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
2837 {
2838 err.primary_message(
2842 "return type should be specified after the function parameters",
2843 );
2844 err.subdiagnostic(errors::MisplacedReturnType {
2845 fn_params_end,
2846 snippet,
2847 ret_ty_span,
2848 });
2849 }
2850 Err(err)
2851 } else {
2852 Err(err)
2853 }
2854 }
2855 }
2856 }
2857
2858 fn parse_fn_body(
2862 &mut self,
2863 attrs: &mut AttrVec,
2864 ident: &Ident,
2865 sig_hi: &mut Span,
2866 req_body: bool,
2867 fn_params_end: Option<Span>,
2868 ) -> PResult<'a, Option<Box<Block>>> {
2869 let has_semi = if req_body {
2870 self.token == TokenKind::Semi
2871 } else {
2872 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))
2874 };
2875 let (inner_attrs, body) = if has_semi {
2876 self.expect_semi()?;
2878 *sig_hi = self.prev_token.span;
2879 (AttrVec::new(), None)
2880 } 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() {
2881 let prev_in_fn_body = self.in_fn_body;
2882 self.in_fn_body = true;
2883 let res = self.parse_block_common(self.token.span, BlockCheckMode::Default, None).map(
2884 |(attrs, mut body)| {
2885 if let Some(guar) = self.fn_body_missing_semi_guar.take() {
2886 body.stmts.push(self.mk_stmt(
2887 body.span,
2888 StmtKind::Expr(self.mk_expr(body.span, ExprKind::Err(guar))),
2889 ));
2890 }
2891 (attrs, Some(body))
2892 },
2893 );
2894 self.in_fn_body = prev_in_fn_body;
2895 res?
2896 } else if self.token == token::Eq {
2897 self.bump(); let eq_sp = self.prev_token.span;
2900 let _ = self.parse_expr()?;
2901 self.expect_semi()?; let span = eq_sp.to(self.prev_token.span);
2903 let guar = self.dcx().emit_err(errors::FunctionBodyEqualsExpr {
2904 span,
2905 sugg: errors::FunctionBodyEqualsExprSugg { eq: eq_sp, semi: self.prev_token.span },
2906 });
2907 (AttrVec::new(), Some(self.mk_block_err(span, guar)))
2908 } else {
2909 self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
2910 (AttrVec::new(), None)
2911 };
2912 attrs.extend(inner_attrs);
2913 Ok(body)
2914 }
2915
2916 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2917 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2918 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)) {
2921 return true;
2922 }
2923 let mut i = 0;
2924 while i < ALL_QUALS.len() {
2925 let action = self.look_ahead(i + look_ahead, |token| {
2926 if token.is_keyword(kw::Impl) {
2927 return Some(true);
2928 }
2929 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2930 return None;
2932 }
2933 Some(false)
2934 });
2935 if let Some(ret) = action {
2936 return ret;
2937 }
2938 i += 1;
2939 }
2940
2941 self.is_keyword_ahead(i, &[kw::Impl])
2942 }
2943
2944 pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
2949 const ALL_QUALS: &[ExpKeywordPair] = &[
2950 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub),
2951 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen),
2952 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const),
2953 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async),
2954 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe),
2955 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe),
2956 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern),
2957 ];
2958
2959 let quals: &[_] = if check_pub {
2964 ALL_QUALS
2965 } else {
2966 &[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)]
2967 };
2968 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))
2971 && self.look_ahead(1, |t| {
2972 t.is_keyword_case(kw::Fn, case)
2974 || (
2976 (
2977 t.is_non_raw_ident_where(|i|
2978 quals.iter().any(|exp| exp.kw == i.name)
2979 && i.is_reserved()
2981 )
2982 || case == Case::Insensitive
2983 && t.is_non_raw_ident_where(|i| quals.iter().any(|exp| {
2984 exp.kw.as_str() == i.name.as_str().to_lowercase()
2985 }))
2986 )
2987 && !self.is_unsafe_foreign_mod()
2989 && !self.is_async_gen_block()
2991 && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait, kw::Impl])
2993 )
2994 })
2995 || 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)
2997 && self.look_ahead(1, |t| t.can_begin_string_literal())
3001 && (self.tree_look_ahead(2, |tt| {
3002 match tt {
3003 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
3004 TokenTree::Delimited(..) => false,
3005 }
3006 }) == Some(true) ||
3007 (self.may_recover()
3010 && self.tree_look_ahead(2, |tt| {
3011 match tt {
3012 TokenTree::Token(t, _) =>
3013 ALL_QUALS.iter().any(|exp| {
3014 t.is_keyword(exp.kw)
3015 }),
3016 TokenTree::Delimited(..) => false,
3017 }
3018 }) == Some(true)
3019 && self.tree_look_ahead(3, |tt| {
3020 match tt {
3021 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
3022 TokenTree::Delimited(..) => false,
3023 }
3024 }) == Some(true)
3025 )
3026 )
3027 }
3028
3029 pub(super) fn parse_fn_front_matter(
3044 &mut self,
3045 orig_vis: &Visibility,
3046 case: Case,
3047 parsing_mode: FrontMatterParsingMode,
3048 ) -> PResult<'a, FnHeader> {
3049 let sp_start = self.token.span;
3050 let constness = self.parse_constness(case);
3051 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3052 && let Const::Yes(const_span) = constness
3053 {
3054 self.dcx().emit_err(FnPointerCannotBeConst {
3055 span: const_span,
3056 suggestion: const_span.until(self.token.span),
3057 });
3058 }
3059
3060 let async_start_sp = self.token.span;
3061 let coroutine_kind = self.parse_coroutine_kind(case);
3062 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3063 && let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind
3064 {
3065 self.dcx().emit_err(FnPointerCannotBeAsync {
3066 span: async_span,
3067 suggestion: async_span.until(self.token.span),
3068 });
3069 }
3070 let unsafe_start_sp = self.token.span;
3073 let safety = self.parse_safety(case);
3074
3075 let ext_start_sp = self.token.span;
3076 let ext = self.parse_extern(case);
3077
3078 if let Some(CoroutineKind::Async { span, .. }) = coroutine_kind {
3079 if span.is_rust_2015() {
3080 self.dcx().emit_err(errors::AsyncFnIn2015 {
3081 span,
3082 help: errors::HelpUseLatestEdition::new(),
3083 });
3084 }
3085 }
3086
3087 match coroutine_kind {
3088 Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
3089 self.psess.gated_spans.gate(sym::gen_blocks, span);
3090 }
3091 Some(CoroutineKind::Async { .. }) | None => {}
3092 }
3093
3094 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) {
3095 match self.expect_one_of(&[], &[]) {
3099 Ok(Recovered::Yes(_)) => {}
3100 Ok(Recovered::No) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3101 Err(mut err) => {
3102 enum WrongKw {
3104 Duplicated(Span),
3105 Misplaced(Span),
3106 MisplacedDisallowedQualifier,
3111 }
3112
3113 let mut recover_constness = constness;
3115 let mut recover_coroutine_kind = coroutine_kind;
3116 let mut recover_safety = safety;
3117 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)) {
3120 match constness {
3121 Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
3122 Const::No => {
3123 recover_constness = Const::Yes(self.token.span);
3124 match parsing_mode {
3125 FrontMatterParsingMode::Function => {
3126 Some(WrongKw::Misplaced(async_start_sp))
3127 }
3128 FrontMatterParsingMode::FunctionPtrType => {
3129 self.dcx().emit_err(FnPointerCannotBeConst {
3130 span: self.token.span,
3131 suggestion: self
3132 .token
3133 .span
3134 .with_lo(self.prev_token.span.hi()),
3135 });
3136 Some(WrongKw::MisplacedDisallowedQualifier)
3137 }
3138 }
3139 }
3140 }
3141 } 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)) {
3142 match coroutine_kind {
3143 Some(CoroutineKind::Async { span, .. }) => {
3144 Some(WrongKw::Duplicated(span))
3145 }
3146 Some(CoroutineKind::AsyncGen { span, .. }) => {
3147 Some(WrongKw::Duplicated(span))
3148 }
3149 Some(CoroutineKind::Gen { .. }) => {
3150 recover_coroutine_kind = Some(CoroutineKind::AsyncGen {
3151 span: self.token.span,
3152 closure_id: DUMMY_NODE_ID,
3153 return_impl_trait_id: DUMMY_NODE_ID,
3154 });
3155 Some(WrongKw::Misplaced(unsafe_start_sp))
3157 }
3158 None => {
3159 recover_coroutine_kind = Some(CoroutineKind::Async {
3160 span: self.token.span,
3161 closure_id: DUMMY_NODE_ID,
3162 return_impl_trait_id: DUMMY_NODE_ID,
3163 });
3164 match parsing_mode {
3165 FrontMatterParsingMode::Function => {
3166 Some(WrongKw::Misplaced(async_start_sp))
3167 }
3168 FrontMatterParsingMode::FunctionPtrType => {
3169 self.dcx().emit_err(FnPointerCannotBeAsync {
3170 span: self.token.span,
3171 suggestion: self
3172 .token
3173 .span
3174 .with_lo(self.prev_token.span.hi()),
3175 });
3176 Some(WrongKw::MisplacedDisallowedQualifier)
3177 }
3178 }
3179 }
3180 }
3181 } 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)) {
3182 match safety {
3183 Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
3184 Safety::Safe(sp) => {
3185 recover_safety = Safety::Unsafe(self.token.span);
3186 Some(WrongKw::Misplaced(sp))
3187 }
3188 Safety::Default => {
3189 recover_safety = Safety::Unsafe(self.token.span);
3190 Some(WrongKw::Misplaced(ext_start_sp))
3191 }
3192 }
3193 } 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)) {
3194 match safety {
3195 Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
3196 Safety::Unsafe(sp) => {
3197 recover_safety = Safety::Safe(self.token.span);
3198 Some(WrongKw::Misplaced(sp))
3199 }
3200 Safety::Default => {
3201 recover_safety = Safety::Safe(self.token.span);
3202 Some(WrongKw::Misplaced(ext_start_sp))
3203 }
3204 }
3205 } else {
3206 None
3207 };
3208
3209 if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw {
3211 let original_kw = self
3212 .span_to_snippet(original_sp)
3213 .expect("Span extracted directly from keyword should always work");
3214
3215 err.span_suggestion(
3216 self.token_uninterpolated_span(),
3217 ::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"),
3218 "",
3219 Applicability::MachineApplicable,
3220 )
3221 .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"));
3222 }
3223 else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
3225 let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
3226 if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
3227 let misplaced_qual_sp = self.token_uninterpolated_span();
3228 let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
3229
3230 err.span_suggestion(
3231 correct_pos_sp.to(misplaced_qual_sp),
3232 ::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}`"),
3233 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", misplaced_qual,
current_qual))
})format!("{misplaced_qual} {current_qual}"),
3234 Applicability::MachineApplicable,
3235 ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
3236 }
3237 }
3238 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)) {
3240 let sp = sp_start.to(self.prev_token.span);
3241 if let Ok(snippet) = self.span_to_snippet(sp) {
3242 let current_vis = match self.parse_visibility(FollowedByType::No) {
3243 Ok(v) => v,
3244 Err(d) => {
3245 d.cancel();
3246 return Err(err);
3247 }
3248 };
3249 let vs = pprust::vis_to_string(¤t_vis);
3250 let vs = vs.trim_end();
3251
3252 if #[allow(non_exhaustive_omitted_patterns)] match orig_vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(orig_vis.kind, VisibilityKind::Inherited) {
3254 err.span_suggestion(
3255 sp_start.to(self.prev_token.span),
3256 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("visibility `{0}` must come before `{1}`",
vs, snippet))
})format!("visibility `{vs}` must come before `{snippet}`"),
3257 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", vs, snippet))
})format!("{vs} {snippet}"),
3258 Applicability::MachineApplicable,
3259 );
3260 }
3261 else {
3263 err.span_suggestion(
3264 current_vis.span,
3265 "there is already a visibility modifier, remove one",
3266 "",
3267 Applicability::MachineApplicable,
3268 )
3269 .span_note(orig_vis.span, "explicit visibility first seen here");
3270 }
3271 }
3272 }
3273
3274 if let Some(wrong_kw) = wrong_kw
3277 && self.may_recover()
3278 && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
3279 {
3280 self.bump();
3282 self.bump();
3283 if #[allow(non_exhaustive_omitted_patterns)] match wrong_kw {
WrongKw::MisplacedDisallowedQualifier => true,
_ => false,
}matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
3286 err.cancel();
3287 } else {
3288 err.emit();
3289 }
3290 return Ok(FnHeader {
3291 constness: recover_constness,
3292 safety: recover_safety,
3293 coroutine_kind: recover_coroutine_kind,
3294 ext,
3295 });
3296 }
3297
3298 return Err(err);
3299 }
3300 }
3301 }
3302
3303 Ok(FnHeader { constness, safety, coroutine_kind, ext })
3304 }
3305
3306 pub(super) fn parse_fn_decl(
3308 &mut self,
3309 fn_parse_mode: &FnParseMode,
3310 ret_allow_plus: AllowPlus,
3311 recover_return_sign: RecoverReturnSign,
3312 ) -> PResult<'a, Box<FnDecl>> {
3313 Ok(Box::new(FnDecl {
3314 inputs: self.parse_fn_params(fn_parse_mode)?,
3315 output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
3316 }))
3317 }
3318
3319 pub(super) fn parse_fn_params(
3321 &mut self,
3322 fn_parse_mode: &FnParseMode,
3323 ) -> PResult<'a, ThinVec<Param>> {
3324 let mut first_param = true;
3325 if self.token != TokenKind::OpenParen
3327 && !self.token.is_keyword(kw::For)
3329 {
3330 self.dcx()
3332 .emit_err(errors::MissingFnParams { span: self.prev_token.span.shrink_to_hi() });
3333 return Ok(ThinVec::new());
3334 }
3335
3336 let (mut params, _) = self.parse_paren_comma_seq(|p| {
3337 p.recover_vcs_conflict_marker();
3338 let snapshot = p.create_snapshot_for_diagnostic();
3339 let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| {
3340 let guar = e.emit();
3341 let lo = if let TokenKind::OpenParen = p.prev_token.kind {
3345 p.prev_token.span.shrink_to_hi()
3346 } else {
3347 p.prev_token.span
3348 };
3349 p.restore_snapshot(snapshot);
3350 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)]);
3352 Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
3354 });
3355 first_param = false;
3357 param
3358 })?;
3359 self.deduplicate_recovered_params_names(&mut params);
3361 Ok(params)
3362 }
3363
3364 pub(super) fn parse_param_general(
3369 &mut self,
3370 fn_parse_mode: &FnParseMode,
3371 first_param: bool,
3372 recover_arg_parse: bool,
3373 ) -> PResult<'a, Param> {
3374 let lo = self.token.span;
3375 let attrs = self.parse_outer_attributes()?;
3376 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3377 if let Some(mut param) = this.parse_self_param()? {
3379 param.attrs = attrs;
3380 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
3381 return Ok((res?, Trailing::No, UsePreAttrPos::No));
3382 }
3383
3384 let is_dot_dot_dot = if this.token.kind == token::DotDotDot {
3385 IsDotDotDot::Yes
3386 } else {
3387 IsDotDotDot::No
3388 };
3389 let is_name_required = (fn_parse_mode.req_name)(
3390 this.token.span.with_neighbor(this.prev_token.span).edition(),
3391 is_dot_dot_dot,
3392 );
3393 let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes {
3394 this.psess.buffer_lint(
3395 VARARGS_WITHOUT_PATTERN,
3396 this.token.span,
3397 ast::CRATE_NODE_ID,
3398 errors::VarargsWithoutPattern { span: this.token.span },
3399 );
3400 false
3401 } else {
3402 is_name_required
3403 };
3404 let (pat, ty) = if is_name_required || this.is_named_param() {
3405 {
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:3405",
"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(3405u32),
::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);
3406 let (pat, colon) = this.parse_fn_param_pat_colon()?;
3407 if !colon {
3408 let mut err = this.unexpected().unwrap_err();
3409 return if let Some(ident) = this.parameter_without_type(
3410 &mut err,
3411 pat,
3412 is_name_required,
3413 first_param,
3414 fn_parse_mode,
3415 ) {
3416 let guar = err.emit();
3417 Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No))
3418 } else {
3419 Err(err)
3420 };
3421 }
3422
3423 this.eat_incorrect_doc_comment_for_param_type();
3424 (pat, this.parse_ty_for_param()?)
3425 } else {
3426 {
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:3426",
"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(3426u32),
::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");
3427 let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
3428 this.eat_incorrect_doc_comment_for_param_type();
3429 let mut ty = this.parse_ty_for_param();
3430
3431 if let Ok(t) = &ty {
3432 if let TyKind::Path(_, Path { segments, .. }) = &t.kind
3434 && let Some(segment) = segments.last()
3435 && let Some(guar) =
3436 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)])
3437 {
3438 return Ok((
3439 dummy_arg(segment.ident, guar),
3440 Trailing::No,
3441 UsePreAttrPos::No,
3442 ));
3443 }
3444
3445 if this.token != token::Comma && this.token != token::CloseParen {
3446 ty = this.unexpected_any();
3449 }
3450 }
3451 match ty {
3452 Ok(ty) => {
3453 let pat = this.mk_pat(ty.span, PatKind::Missing);
3454 (Box::new(pat), ty)
3455 }
3456 Err(err) if this.token == token::DotDotDot => return Err(err),
3458 Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
3459 Err(err) if recover_arg_parse => {
3460 err.cancel();
3462 this.restore_snapshot(parser_snapshot_before_ty);
3463 this.recover_arg_parse()?
3464 }
3465 Err(err) => return Err(err),
3466 }
3467 };
3468
3469 let span = lo.to(this.prev_token.span);
3470
3471 Ok((
3472 Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
3473 Trailing::No,
3474 UsePreAttrPos::No,
3475 ))
3476 })
3477 }
3478
3479 fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
3481 let expect_self_ident = |this: &mut Self| match this.token.ident() {
3483 Some((ident, IdentIsRaw::No)) => {
3484 this.bump();
3485 ident
3486 }
3487 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3488 };
3489 let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime());
3491 let is_isolated_self = |this: &Self, n| {
3493 this.is_keyword_ahead(n, &[kw::SelfLower])
3494 && this.look_ahead(n + 1, |t| t != &token::PathSep)
3495 };
3496 let is_isolated_pin_const_self = |this: &Self, n| {
3498 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3499 && this.is_keyword_ahead(n + 1, &[kw::Const])
3500 && is_isolated_self(this, n + 2)
3501 };
3502 let is_isolated_mut_self =
3504 |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
3505 let is_isolated_pin_mut_self = |this: &Self, n| {
3507 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3508 && is_isolated_mut_self(this, n + 1)
3509 };
3510 let parse_self_possibly_typed = |this: &mut Self, m| {
3512 let eself_ident = expect_self_ident(this);
3513 let eself_hi = this.prev_token.span;
3514 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)) {
3515 SelfKind::Explicit(this.parse_ty()?, m)
3516 } else {
3517 SelfKind::Value(m)
3518 };
3519 Ok((eself, eself_ident, eself_hi))
3520 };
3521 let expect_self_ident_not_typed =
3522 |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
3523 let eself_ident = expect_self_ident(this);
3524
3525 if this.may_recover() && this.eat_noexpect(&token::Colon) {
3527 let snap = this.create_snapshot_for_diagnostic();
3528 match this.parse_ty() {
3529 Ok(ty) => {
3530 this.dcx().emit_err(errors::IncorrectTypeOnSelf {
3531 span: ty.span,
3532 move_self_modifier: errors::MoveSelfModifier {
3533 removal_span: modifier_span,
3534 insertion_span: ty.span.shrink_to_lo(),
3535 modifier: modifier.to_ref_suggestion(),
3536 },
3537 });
3538 }
3539 Err(diag) => {
3540 diag.cancel();
3541 this.restore_snapshot(snap);
3542 }
3543 }
3544 }
3545 eself_ident
3546 };
3547 let recover_self_ptr = |this: &mut Self| {
3549 this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
3550
3551 Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
3552 };
3553
3554 let eself_lo = self.token.span;
3558 let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
3559 token::And => {
3560 let has_lifetime = is_lifetime(self, 1);
3561 let skip_lifetime_count = has_lifetime as usize;
3562 let eself = if is_isolated_self(self, skip_lifetime_count + 1) {
3563 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3566 SelfKind::Region(lifetime, Mutability::Not)
3567 } else if is_isolated_mut_self(self, skip_lifetime_count + 1) {
3568 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3571 self.bump(); SelfKind::Region(lifetime, Mutability::Mut)
3573 } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) {
3574 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3577 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3578 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Not)
3581 } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) {
3582 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3585 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3586 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Mut)
3589 } else {
3590 return Ok(None);
3592 };
3593 let hi = self.token.span;
3594 let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
3595 (eself, self_ident, hi)
3596 }
3597 token::Star if is_isolated_self(self, 1) => {
3599 self.bump();
3600 recover_self_ptr(self)?
3601 }
3602 token::Star
3604 if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
3605 {
3606 self.bump();
3607 self.bump();
3608 recover_self_ptr(self)?
3609 }
3610 token::Ident(..) if is_isolated_self(self, 0) => {
3612 parse_self_possibly_typed(self, Mutability::Not)?
3613 }
3614 token::Ident(..) if is_isolated_mut_self(self, 0) => {
3616 self.bump();
3617 parse_self_possibly_typed(self, Mutability::Mut)?
3618 }
3619 _ => return Ok(None),
3620 };
3621
3622 let eself = respan(eself_lo.to(eself_hi), eself);
3623 Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
3624 }
3625
3626 fn is_named_param(&self) -> bool {
3627 let offset = match &self.token.kind {
3628 token::OpenInvisible(origin) => match origin {
3629 InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
3630 return self.check_noexpect_past_close_delim(&token::Colon);
3631 }
3632 _ => 0,
3633 },
3634 token::And | token::AndAnd => 1,
3635 _ if self.token.is_keyword(kw::Mut) => 1,
3636 _ => 0,
3637 };
3638
3639 self.look_ahead(offset, |t| t.is_ident())
3640 && self.look_ahead(offset + 1, |t| t == &token::Colon)
3641 }
3642
3643 fn recover_self_param(&mut self) -> bool {
3644 #[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!(
3645 self.parse_outer_attributes()
3646 .and_then(|_| self.parse_self_param())
3647 .map_err(|e| e.cancel()),
3648 Ok(Some(_))
3649 )
3650 }
3651
3652 fn try_recover_const_missing_semi(
3660 &mut self,
3661 rhs: &ConstItemRhsKind,
3662 const_span: Span,
3663 ) -> Option<Box<Expr>> {
3664 if self.token == TokenKind::Semi {
3665 return None;
3666 }
3667 let ConstItemRhsKind::Body { rhs: Some(rhs) } = rhs else {
3668 return None;
3669 };
3670 if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
3671 return None;
3672 }
3673 if let Some((span, guar)) =
3674 self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
3675 {
3676 self.fn_body_missing_semi_guar = Some(guar);
3677 Some(self.mk_expr(span, ExprKind::Err(guar)))
3678 } else {
3679 None
3680 }
3681 }
3682}
3683
3684enum IsMacroRulesItem {
3685 Yes { has_bang: bool },
3686 No,
3687}
3688
3689#[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)]
3690pub(super) enum FrontMatterParsingMode {
3691 Function,
3693 FunctionPtrType,
3696}