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 source: DelegationSource::Single,
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 span = vlo.to(this.prev_token.span);
1919 if ident.name == kw::Underscore {
1920 this.psess.gated_spans.gate(sym::unnamed_enum_variants, span);
1921 }
1922 let vr = ast::Variant {
1923 ident,
1924 vis,
1925 id: DUMMY_NODE_ID,
1926 attrs: variant_attrs,
1927 data: struct_def,
1928 disr_expr,
1929 span,
1930 is_placeholder: false,
1931 };
1932
1933 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
1934 })
1935 .map_err(|mut err| {
1936 err.help(help);
1937 err
1938 })
1939 }
1940
1941 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
1943 let ident = self.parse_ident()?;
1944
1945 let mut generics = self.parse_generics()?;
1946
1947 let vdata = if self.token.is_keyword(kw::Where) {
1962 let tuple_struct_body;
1963 (generics.where_clause, tuple_struct_body) =
1964 self.parse_struct_where_clause(ident, generics.span)?;
1965
1966 if let Some(body) = tuple_struct_body {
1967 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
1969 self.expect_semi()?;
1970 body
1971 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1972 VariantData::Unit(DUMMY_NODE_ID)
1974 } else {
1975 let (fields, recovered) = self.parse_record_struct_body(
1977 "struct",
1978 ident.span,
1979 generics.where_clause.has_where_token,
1980 )?;
1981 VariantData::Struct { fields, recovered }
1982 }
1983 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1985 VariantData::Unit(DUMMY_NODE_ID)
1986 } else if self.token == token::OpenBrace {
1988 let (fields, recovered) = self.parse_record_struct_body(
1989 "struct",
1990 ident.span,
1991 generics.where_clause.has_where_token,
1992 )?;
1993 VariantData::Struct { fields, recovered }
1994 } else if self.token == token::OpenParen {
1996 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
1997 generics.where_clause = self.parse_where_clause()?;
1998 self.expect_semi()?;
1999 body
2000 } else {
2001 let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
2002 return Err(self.dcx().create_err(err));
2003 };
2004
2005 Ok(ItemKind::Struct(ident, generics, vdata))
2006 }
2007
2008 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
2010 let ident = self.parse_ident()?;
2011
2012 let mut generics = self.parse_generics()?;
2013
2014 let vdata = if self.token.is_keyword(kw::Where) {
2015 generics.where_clause = self.parse_where_clause()?;
2016 let (fields, recovered) = self.parse_record_struct_body(
2017 "union",
2018 ident.span,
2019 generics.where_clause.has_where_token,
2020 )?;
2021 VariantData::Struct { fields, recovered }
2022 } else if self.token == token::OpenBrace {
2023 let (fields, recovered) = self.parse_record_struct_body(
2024 "union",
2025 ident.span,
2026 generics.where_clause.has_where_token,
2027 )?;
2028 VariantData::Struct { fields, recovered }
2029 } else {
2030 let token_str = super::token_descr(&self.token);
2031 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}");
2032 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2033 err.span_label(self.token.span, "expected `where` or `{` after union name");
2034 return Err(err);
2035 };
2036
2037 Ok(ItemKind::Union(ident, generics, vdata))
2038 }
2039
2040 pub(crate) fn parse_record_struct_body(
2045 &mut self,
2046 adt_ty: &str,
2047 ident_span: Span,
2048 parsed_where: bool,
2049 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
2050 let mut fields = ThinVec::new();
2051 let mut recovered = Recovered::No;
2052 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2053 while self.token != token::CloseBrace {
2054 match self.parse_field_def(adt_ty, ident_span) {
2055 Ok(field) => {
2056 fields.push(field);
2057 }
2058 Err(mut err) => {
2059 self.consume_block(
2060 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
2061 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
2062 ConsumeClosingDelim::No,
2063 );
2064 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}"));
2065 let guar = err.emit();
2066 recovered = Recovered::Yes(guar);
2067 break;
2068 }
2069 }
2070 }
2071 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
2072 } else {
2073 let token_str = super::token_descr(&self.token);
2074 let where_str = if parsed_where { "" } else { "`where`, or " };
2075 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}");
2076 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2077 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",));
2078 return Err(err);
2079 }
2080
2081 Ok((fields, recovered))
2082 }
2083
2084 fn parse_unsafe_field(&mut self) -> Safety {
2085 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)) {
2087 let span = self.prev_token.span;
2088 self.psess.gated_spans.gate(sym::unsafe_fields, span);
2089 Safety::Unsafe(span)
2090 } else {
2091 Safety::Default
2092 }
2093 }
2094 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
2097 let openparen_span = self.token.span;
2098 let mut encountered_colon = false;
2099 self.parse_paren_comma_seq(|p| {
2100 let attrs = p.parse_outer_attributes()?;
2101 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
2102 let mut snapshot = None;
2103 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
2104 snapshot = Some(p.create_snapshot_for_diagnostic());
2108 }
2109 let lo = p.token.span;
2110 let vis = match p.parse_visibility(FollowedByType::Yes) {
2111 Ok(vis) => vis,
2112 Err(err) => {
2113 if let Some(ref mut snapshot) = snapshot {
2114 snapshot.recover_vcs_conflict_marker();
2115 }
2116 return Err(err);
2117 }
2118 };
2119 let mut_restriction = p.parse_mut_restriction()?;
2120 encountered_colon |=
2121 p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
2122 let ty = match p.parse_ty() {
2125 Ok(ty) => ty,
2126 Err(err) => {
2127 if let Some(ref mut snapshot) = snapshot {
2128 snapshot.recover_vcs_conflict_marker();
2129 }
2130 return Err(err);
2131 }
2132 };
2133 let mut default = None;
2134 if p.token == token::Eq {
2135 let mut snapshot = p.create_snapshot_for_diagnostic();
2136 snapshot.bump();
2137 match snapshot.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst) {
2138 Ok(const_expr) => {
2139 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2140 p.psess.gated_spans.gate(sym::default_field_values, sp);
2141 p.restore_snapshot(snapshot);
2142 default = Some(const_expr);
2143 }
2144 Err(err) => {
2145 err.cancel();
2146 }
2147 }
2148 }
2149
2150 Ok((
2151 FieldDef {
2152 span: lo.to(ty.span),
2153 vis,
2154 mut_restriction,
2155 safety: Safety::Default,
2156 ident: None,
2157 id: DUMMY_NODE_ID,
2158 ty,
2159 default,
2160 attrs,
2161 is_placeholder: false,
2162 },
2163 Trailing::from(p.token == token::Comma),
2164 UsePreAttrPos::No,
2165 ))
2166 })
2167 })
2168 .map(|(r, _)| r)
2169 .map_err(|mut error| {
2170 if self.token == token::Colon {
2171 error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
2172 }
2173 if encountered_colon {
2174 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
2175 self.bump();
2176 error.subdiagnostic(UseRegularStructSuggestion {
2177 open: openparen_span,
2178 close: self.prev_token.span,
2179 semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
2180 });
2181 }
2182 error
2183 })
2184 }
2185
2186 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2188 self.recover_vcs_conflict_marker();
2189 let attrs = self.parse_outer_attributes()?;
2190 self.recover_vcs_conflict_marker();
2191 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2192 let lo = this.token.span;
2193 let vis = this.parse_visibility(FollowedByType::No)?;
2194 let mut_restriction = this.parse_mut_restriction()?;
2195 let safety = this.parse_unsafe_field();
2196 this.parse_single_struct_field(
2197 adt_ty,
2198 lo,
2199 vis,
2200 mut_restriction,
2201 safety,
2202 attrs,
2203 ident_span,
2204 )
2205 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2206 })
2207 }
2208
2209 fn parse_single_struct_field(
2211 &mut self,
2212 adt_ty: &str,
2213 lo: Span,
2214 vis: Visibility,
2215 mut_restriction: MutRestriction,
2216 safety: Safety,
2217 attrs: AttrVec,
2218 ident_span: Span,
2219 ) -> PResult<'a, FieldDef> {
2220 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, mut_restriction, safety, attrs)?;
2221 match self.token.kind {
2222 token::Comma => {
2223 self.bump();
2224 }
2225 token::Semi => {
2226 self.bump();
2227 let sp = self.prev_token.span;
2228 let mut err =
2229 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 `,`"));
2230 err.span_suggestion_short(
2231 sp,
2232 "replace `;` with `,`",
2233 ",",
2234 Applicability::MachineApplicable,
2235 );
2236 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}"));
2237 err.emit();
2238 }
2239 token::CloseBrace => {}
2240 token::DocComment(..) => {
2241 let previous_span = self.prev_token.span;
2242 let mut err = errors::DocCommentDoesNotDocumentAnything {
2243 span: self.token.span,
2244 missing_comma: None,
2245 };
2246 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 {
2248 self.dcx().emit_err(err);
2249 } else {
2250 let sp = previous_span.shrink_to_hi();
2251 err.missing_comma = Some(sp);
2252 return Err(self.dcx().create_err(err));
2253 }
2254 }
2255 _ => {
2256 let sp = self.prev_token.span.shrink_to_hi();
2257 let msg =
2258 ::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));
2259
2260 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2262 && let Some(last_segment) = segments.last()
2263 {
2264 let guar = self.check_trailing_angle_brackets(
2265 last_segment,
2266 &[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)],
2267 );
2268 if let Some(_guar) = guar {
2269 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2272
2273 return Ok(a_var);
2276 }
2277 }
2278
2279 let mut err = self.dcx().struct_span_err(sp, msg);
2280
2281 if self.token.is_ident()
2282 || (self.token == TokenKind::Pound
2283 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2284 {
2285 err.span_suggestion(
2288 sp,
2289 "try adding a comma",
2290 ",",
2291 Applicability::MachineApplicable,
2292 );
2293 err.emit();
2294 } else {
2295 return Err(err);
2296 }
2297 }
2298 }
2299 Ok(a_var)
2300 }
2301
2302 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2303 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)) {
2304 let sm = self.psess.source_map();
2305 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2306 let semi_typo = self.token == token::Semi
2307 && self.look_ahead(1, |t| {
2308 t.is_path_start()
2309 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2312 (Ok(l), Ok(r)) => l.line == r.line,
2313 _ => true,
2314 }
2315 });
2316 if eq_typo || semi_typo {
2317 self.bump();
2318 err.with_span_suggestion_short(
2320 self.prev_token.span,
2321 "field names and their types are separated with `:`",
2322 ":",
2323 Applicability::MachineApplicable,
2324 )
2325 .emit();
2326 } else {
2327 return Err(err);
2328 }
2329 }
2330 Ok(())
2331 }
2332
2333 fn parse_name_and_ty(
2335 &mut self,
2336 adt_ty: &str,
2337 lo: Span,
2338 vis: Visibility,
2339 mut_restriction: MutRestriction,
2340 safety: Safety,
2341 attrs: AttrVec,
2342 ) -> PResult<'a, FieldDef> {
2343 let name = self.parse_field_ident(adt_ty, lo)?;
2344 if self.token == token::Bang {
2345 if let Err(mut err) = self.unexpected() {
2346 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2348 return Err(err);
2349 }
2350 }
2351 self.expect_field_ty_separator()?;
2352 let ty = self.parse_ty()?;
2353 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2354 self.dcx()
2355 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2356 .with_span_suggestion_verbose(
2357 self.token.span,
2358 "write a path separator here",
2359 "::",
2360 Applicability::MaybeIncorrect,
2361 )
2362 .emit();
2363 }
2364 let default = if self.token == token::Eq {
2365 self.bump();
2366 let const_expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
2367 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2368 self.psess.gated_spans.gate(sym::default_field_values, sp);
2369 Some(const_expr)
2370 } else {
2371 None
2372 };
2373 Ok(FieldDef {
2374 span: lo.to(self.prev_token.span),
2375 ident: Some(name),
2376 vis,
2377 safety,
2378 mut_restriction,
2379 id: DUMMY_NODE_ID,
2380 ty,
2381 default,
2382 attrs,
2383 is_placeholder: false,
2384 })
2385 }
2386
2387 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2390 let (ident, is_raw) = self.ident_or_err(true)?;
2391 if is_raw == IdentIsRaw::No
2392 && ident.is_reserved()
2393 && !(ident.name == kw::Underscore && adt_ty == "enum")
2394 {
2395 let snapshot = self.create_snapshot_for_diagnostic();
2396 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2397 let inherited_vis =
2398 Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
2399 let fn_parse_mode =
2401 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2402 match self.parse_fn(
2403 &mut AttrVec::new(),
2404 fn_parse_mode,
2405 lo,
2406 &inherited_vis,
2407 Case::Insensitive,
2408 ) {
2409 Ok(_) => {
2410 self.dcx().struct_span_err(
2411 lo.to(self.prev_token.span),
2412 ::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"),
2413 )
2414 .with_help(
2415 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2416 )
2417 .with_help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information")
2418 }
2419 Err(err) => {
2420 err.cancel();
2421 self.restore_snapshot(snapshot);
2422 self.expected_ident_found_err()
2423 }
2424 }
2425 } 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)) {
2426 match self.parse_item_struct() {
2427 Ok(item) => {
2428 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2429 self.dcx()
2430 .struct_span_err(
2431 lo.with_hi(ident.span.hi()),
2432 ::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"),
2433 )
2434 .with_help(
2435 "consider creating a new `struct` definition instead of nesting",
2436 )
2437 }
2438 Err(err) => {
2439 err.cancel();
2440 self.restore_snapshot(snapshot);
2441 self.expected_ident_found_err()
2442 }
2443 }
2444 } else {
2445 let mut err = self.expected_ident_found_err();
2446 if self.eat_keyword_noexpect(kw::Let)
2447 && let removal_span = self.prev_token.span.until(self.token.span)
2448 && let Ok(ident) = self
2449 .parse_ident_common(false)
2450 .map_err(|err| err.cancel())
2452 && self.token == TokenKind::Colon
2453 {
2454 err.span_suggestion(
2455 removal_span,
2456 "remove this `let` keyword",
2457 String::new(),
2458 Applicability::MachineApplicable,
2459 );
2460 err.note("the `let` keyword is not allowed in `struct` fields");
2461 err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
2462 err.emit();
2463 return Ok(ident);
2464 } else {
2465 self.restore_snapshot(snapshot);
2466 }
2467 err
2468 };
2469 return Err(err);
2470 }
2471 self.bump();
2472 Ok(ident)
2473 }
2474
2475 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2483 let ident = self.parse_ident()?;
2484 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)) {
2485 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)) {
2487 let params = self.parse_token_tree(); let pspan = params.span();
2489 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2490 self.unexpected()?;
2491 }
2492 let body = self.parse_token_tree(); let bspan = body.span();
2495 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]);
2497 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2498 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2499 } else {
2500 self.unexpected_any()?
2501 };
2502
2503 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2504 Ok(ItemKind::MacroDef(
2505 ident,
2506 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2507 ))
2508 }
2509
2510 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2512 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)) {
2513 let macro_rules_span = self.token.span;
2514
2515 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2516 return IsMacroRulesItem::Yes { has_bang: true };
2517 } else if self.look_ahead(1, |t| t.is_ident()) {
2518 self.dcx().emit_err(errors::MacroRulesMissingBang {
2520 span: macro_rules_span,
2521 hi: macro_rules_span.shrink_to_hi(),
2522 });
2523
2524 return IsMacroRulesItem::Yes { has_bang: false };
2525 }
2526 }
2527
2528 IsMacroRulesItem::No
2529 }
2530
2531 fn parse_item_macro_rules(
2533 &mut self,
2534 vis: &Visibility,
2535 has_bang: bool,
2536 ) -> PResult<'a, ItemKind> {
2537 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 {
2540 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2542 let ident = self.parse_ident()?;
2543
2544 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2545 let span = self.prev_token.span;
2547 self.dcx().emit_err(errors::MacroNameRemoveBang { span });
2548 }
2549
2550 let body = self.parse_delim_args()?;
2551 self.eat_semi_for_macro_if_needed(&body, None);
2552 self.complain_if_pub_macro(vis, true);
2553
2554 Ok(ItemKind::MacroDef(
2555 ident,
2556 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2557 ))
2558 }
2559
2560 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2563 if let VisibilityKind::Inherited = vis.kind {
2564 return;
2565 }
2566
2567 let vstr = pprust::vis_to_string(vis);
2568 let vstr = vstr.trim_end();
2569 if macro_rules {
2570 self.dcx().emit_err(errors::MacroRulesVisibility { span: vis.span, vis: vstr });
2571 } else {
2572 self.dcx().emit_err(errors::MacroInvocationVisibility { span: vis.span, vis: vstr });
2573 }
2574 }
2575
2576 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
2577 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)) {
2578 self.report_invalid_macro_expansion_item(args, path);
2579 }
2580 }
2581
2582 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
2583 let span = args.dspan.entire();
2584 let mut err = self.dcx().struct_span_err(
2585 span,
2586 "macros that expand to items must be delimited with braces or followed by a semicolon",
2587 );
2588 if !span.from_expansion() {
2591 let DelimSpan { open, close } = args.dspan;
2592 if let Some(path) = path
2595 && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2596 && args.delim == Delimiter::Parenthesis
2597 {
2598 let replace =
2599 if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2600 err.multipart_suggestion(
2601 "to define a macro, remove the parentheses around the macro name",
2602 ::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())],
2603 Applicability::MachineApplicable,
2604 );
2605 } else {
2606 err.multipart_suggestion(
2607 "change the delimiters to curly braces",
2608 ::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())],
2609 Applicability::MaybeIncorrect,
2610 );
2611 err.span_suggestion(
2612 span.with_neighbor(self.token.span).shrink_to_hi(),
2613 "add a semicolon",
2614 ';',
2615 Applicability::MaybeIncorrect,
2616 );
2617 }
2618 }
2619 err.emit();
2620 }
2621
2622 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2625 if (self.token.is_keyword(kw::Enum)
2626 || self.token.is_keyword(kw::Struct)
2627 || self.token.is_keyword(kw::Union))
2628 && self.look_ahead(1, |t| t.is_ident())
2629 {
2630 let kw_token = self.token;
2631 let kw_str = pprust::token_to_string(&kw_token);
2632 let item = self.parse_item(
2633 ForceCollect::No,
2634 AllowConstBlockItems::DoesNotMatter, )?;
2636 let mut item = item.unwrap().span;
2637 if self.token == token::Comma {
2638 item = item.to(self.token.span);
2639 }
2640 self.dcx().emit_err(errors::NestedAdt {
2641 span: kw_token.span,
2642 item,
2643 kw_str,
2644 keyword: keyword.as_str(),
2645 });
2646 return Ok(false);
2648 }
2649 Ok(true)
2650 }
2651}
2652
2653type ReqName = fn(Edition, IsDotDotDot) -> bool;
2662
2663#[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)]
2664pub(crate) enum IsDotDotDot {
2665 Yes,
2666 No,
2667}
2668
2669#[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)]
2677pub(crate) struct FnParseMode {
2678 pub(super) req_name: ReqName,
2704 pub(super) context: FnContext,
2707 pub(super) req_body: bool,
2726}
2727
2728#[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)]
2731pub(crate) enum FnContext {
2732 Free,
2734 Trait,
2736 Impl,
2738}
2739
2740impl<'a> Parser<'a> {
2742 fn parse_fn(
2744 &mut self,
2745 attrs: &mut AttrVec,
2746 fn_parse_mode: FnParseMode,
2747 sig_lo: Span,
2748 vis: &Visibility,
2749 case: Case,
2750 ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
2751 let fn_span = self.token.span;
2752 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)
2756 {
2757 Ok(decl) => decl,
2758 Err(old_err) => {
2759 if self.token.is_keyword(kw::For) {
2761 old_err.cancel();
2762 return Err(self.dcx().create_err(errors::FnTypoWithImpl { fn_span }));
2763 } else {
2764 return Err(old_err);
2765 }
2766 }
2767 };
2768
2769 let fn_params_end = self.prev_token.span.shrink_to_hi();
2772
2773 let contract = self.parse_contract()?;
2774
2775 generics.where_clause = self.parse_where_clause()?; let fn_params_end =
2779 if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
2780
2781 let mut sig_hi = self.prev_token.span;
2782 let body =
2784 self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
2785 let fn_sig_span = sig_lo.to(sig_hi);
2786 Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
2787 }
2788
2789 fn error_fn_body_not_found(
2791 &mut self,
2792 ident_span: Span,
2793 req_body: bool,
2794 fn_params_end: Option<Span>,
2795 ) -> PResult<'a, ErrorGuaranteed> {
2796 let expected: &[_] =
2797 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)] };
2798 match self.expected_one_of_not_found(&[], expected) {
2799 Ok(error_guaranteed) => Ok(error_guaranteed),
2800 Err(mut err) => {
2801 if self.token == token::CloseBrace {
2802 err.span_label(ident_span, "while parsing this `fn`");
2805 Ok(err.emit())
2806 } else if self.token == token::RArrow
2807 && let Some(fn_params_end) = fn_params_end
2808 {
2809 let fn_trait_span =
2815 [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
2816 if self.prev_token.is_ident_named(symbol) {
2817 Some(self.prev_token.span)
2818 } else {
2819 None
2820 }
2821 });
2822
2823 let arrow_span = self.token.span;
2828 let ty_span = match self.parse_ret_ty(
2829 AllowPlus::Yes,
2830 RecoverQPath::Yes,
2831 RecoverReturnSign::Yes,
2832 ) {
2833 Ok(ty_span) => ty_span.span().shrink_to_hi(),
2834 Err(parse_error) => {
2835 parse_error.cancel();
2836 return Err(err);
2837 }
2838 };
2839 let ret_ty_span = arrow_span.to(ty_span);
2840
2841 if let Some(fn_trait_span) = fn_trait_span {
2842 err.subdiagnostic(errors::FnTraitMissingParen { span: fn_trait_span });
2845 } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
2846 {
2847 err.primary_message(
2851 "return type should be specified after the function parameters",
2852 );
2853 err.subdiagnostic(errors::MisplacedReturnType {
2854 fn_params_end,
2855 snippet,
2856 ret_ty_span,
2857 });
2858 }
2859 Err(err)
2860 } else {
2861 Err(err)
2862 }
2863 }
2864 }
2865 }
2866
2867 fn parse_fn_body(
2871 &mut self,
2872 attrs: &mut AttrVec,
2873 ident: &Ident,
2874 sig_hi: &mut Span,
2875 req_body: bool,
2876 fn_params_end: Option<Span>,
2877 ) -> PResult<'a, Option<Box<Block>>> {
2878 let has_semi = if req_body {
2879 self.token == TokenKind::Semi
2880 } else {
2881 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))
2883 };
2884 let (inner_attrs, body) = if has_semi {
2885 self.expect_semi()?;
2887 *sig_hi = self.prev_token.span;
2888 (AttrVec::new(), None)
2889 } 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() {
2890 let prev_in_fn_body = self.in_fn_body;
2891 self.in_fn_body = true;
2892 let res = self.parse_block_common(self.token.span, BlockCheckMode::Default, None).map(
2893 |(attrs, mut body)| {
2894 if let Some(guar) = self.fn_body_missing_semi_guar.take() {
2895 body.stmts.push(self.mk_stmt(
2896 body.span,
2897 StmtKind::Expr(self.mk_expr(body.span, ExprKind::Err(guar))),
2898 ));
2899 }
2900 (attrs, Some(body))
2901 },
2902 );
2903 self.in_fn_body = prev_in_fn_body;
2904 res?
2905 } else if self.token == token::Eq {
2906 self.bump(); let eq_sp = self.prev_token.span;
2909 let _ = self.parse_expr()?;
2910 self.expect_semi()?; let span = eq_sp.to(self.prev_token.span);
2912 let guar = self.dcx().emit_err(errors::FunctionBodyEqualsExpr {
2913 span,
2914 sugg: errors::FunctionBodyEqualsExprSugg { eq: eq_sp, semi: self.prev_token.span },
2915 });
2916 (AttrVec::new(), Some(self.mk_block_err(span, guar)))
2917 } else {
2918 self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
2919 (AttrVec::new(), None)
2920 };
2921 attrs.extend(inner_attrs);
2922 Ok(body)
2923 }
2924
2925 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2926 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2927 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)) {
2930 return true;
2931 }
2932 let mut i = 0;
2933 while i < ALL_QUALS.len() {
2934 let action = self.look_ahead(i + look_ahead, |token| {
2935 if token.is_keyword(kw::Impl) {
2936 return Some(true);
2937 }
2938 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2939 return None;
2941 }
2942 Some(false)
2943 });
2944 if let Some(ret) = action {
2945 return ret;
2946 }
2947 i += 1;
2948 }
2949
2950 self.is_keyword_ahead(i, &[kw::Impl])
2951 }
2952
2953 pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
2958 const ALL_QUALS: &[ExpKeywordPair] = &[
2959 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub),
2960 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen),
2961 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const),
2962 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async),
2963 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe),
2964 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe),
2965 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern),
2966 ];
2967
2968 let quals: &[_] = if check_pub {
2973 ALL_QUALS
2974 } else {
2975 &[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)]
2976 };
2977 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))
2980 && self.look_ahead(1, |t| {
2981 t.is_keyword_case(kw::Fn, case)
2983 || (
2985 (
2986 t.is_non_raw_ident_where(|i|
2987 quals.iter().any(|exp| exp.kw == i.name)
2988 && i.is_reserved()
2990 )
2991 || case == Case::Insensitive
2992 && t.is_non_raw_ident_where(|i| quals.iter().any(|exp| {
2993 exp.kw.as_str() == i.name.as_str().to_lowercase()
2994 }))
2995 )
2996 && !self.is_unsafe_foreign_mod()
2998 && !self.is_async_gen_block()
3000 && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait, kw::Impl])
3002 )
3003 })
3004 || 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)
3006 && self.look_ahead(1, |t| t.can_begin_string_literal())
3010 && (self.tree_look_ahead(2, |tt| {
3011 match tt {
3012 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
3013 TokenTree::Delimited(..) => false,
3014 }
3015 }) == Some(true) ||
3016 (self.may_recover()
3019 && self.tree_look_ahead(2, |tt| {
3020 match tt {
3021 TokenTree::Token(t, _) =>
3022 ALL_QUALS.iter().any(|exp| {
3023 t.is_keyword(exp.kw)
3024 }),
3025 TokenTree::Delimited(..) => false,
3026 }
3027 }) == Some(true)
3028 && self.tree_look_ahead(3, |tt| {
3029 match tt {
3030 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
3031 TokenTree::Delimited(..) => false,
3032 }
3033 }) == Some(true)
3034 )
3035 )
3036 }
3037
3038 pub(super) fn parse_fn_front_matter(
3053 &mut self,
3054 orig_vis: &Visibility,
3055 case: Case,
3056 parsing_mode: FrontMatterParsingMode,
3057 ) -> PResult<'a, FnHeader> {
3058 let sp_start = self.token.span;
3059 let constness = self.parse_constness(case);
3060 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3061 && let Const::Yes(const_span) = constness
3062 {
3063 self.dcx().emit_err(FnPointerCannotBeConst {
3064 span: const_span,
3065 suggestion: const_span.until(self.token.span),
3066 });
3067 }
3068
3069 let async_start_sp = self.token.span;
3070 let coroutine_kind = self.parse_coroutine_kind(case);
3071 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3072 && let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind
3073 {
3074 self.dcx().emit_err(FnPointerCannotBeAsync {
3075 span: async_span,
3076 suggestion: async_span.until(self.token.span),
3077 });
3078 }
3079 let unsafe_start_sp = self.token.span;
3082 let safety = self.parse_safety(case);
3083
3084 let ext_start_sp = self.token.span;
3085 let ext = self.parse_extern(case);
3086
3087 if let Some(CoroutineKind::Async { span, .. }) = coroutine_kind {
3088 if span.is_rust_2015() {
3089 self.dcx().emit_err(errors::AsyncFnIn2015 {
3090 span,
3091 help: errors::HelpUseLatestEdition::new(),
3092 });
3093 }
3094 }
3095
3096 match coroutine_kind {
3097 Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
3098 self.psess.gated_spans.gate(sym::gen_blocks, span);
3099 }
3100 Some(CoroutineKind::Async { .. }) | None => {}
3101 }
3102
3103 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) {
3104 match self.expect_one_of(&[], &[]) {
3108 Ok(Recovered::Yes(_)) => {}
3109 Ok(Recovered::No) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3110 Err(mut err) => {
3111 enum WrongKw {
3113 Duplicated(Span),
3114 Misplaced(Span),
3115 MisplacedDisallowedQualifier,
3120 }
3121
3122 let mut recover_constness = constness;
3124 let mut recover_coroutine_kind = coroutine_kind;
3125 let mut recover_safety = safety;
3126 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)) {
3129 match constness {
3130 Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
3131 Const::No => {
3132 recover_constness = Const::Yes(self.token.span);
3133 match parsing_mode {
3134 FrontMatterParsingMode::Function => {
3135 Some(WrongKw::Misplaced(async_start_sp))
3136 }
3137 FrontMatterParsingMode::FunctionPtrType => {
3138 self.dcx().emit_err(FnPointerCannotBeConst {
3139 span: self.token.span,
3140 suggestion: self
3141 .token
3142 .span
3143 .with_lo(self.prev_token.span.hi()),
3144 });
3145 Some(WrongKw::MisplacedDisallowedQualifier)
3146 }
3147 }
3148 }
3149 }
3150 } 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)) {
3151 match coroutine_kind {
3152 Some(CoroutineKind::Async { span, .. }) => {
3153 Some(WrongKw::Duplicated(span))
3154 }
3155 Some(CoroutineKind::AsyncGen { span, .. }) => {
3156 Some(WrongKw::Duplicated(span))
3157 }
3158 Some(CoroutineKind::Gen { .. }) => {
3159 recover_coroutine_kind = Some(CoroutineKind::AsyncGen {
3160 span: self.token.span,
3161 closure_id: DUMMY_NODE_ID,
3162 return_impl_trait_id: DUMMY_NODE_ID,
3163 });
3164 Some(WrongKw::Misplaced(unsafe_start_sp))
3166 }
3167 None => {
3168 recover_coroutine_kind = Some(CoroutineKind::Async {
3169 span: self.token.span,
3170 closure_id: DUMMY_NODE_ID,
3171 return_impl_trait_id: DUMMY_NODE_ID,
3172 });
3173 match parsing_mode {
3174 FrontMatterParsingMode::Function => {
3175 Some(WrongKw::Misplaced(async_start_sp))
3176 }
3177 FrontMatterParsingMode::FunctionPtrType => {
3178 self.dcx().emit_err(FnPointerCannotBeAsync {
3179 span: self.token.span,
3180 suggestion: self
3181 .token
3182 .span
3183 .with_lo(self.prev_token.span.hi()),
3184 });
3185 Some(WrongKw::MisplacedDisallowedQualifier)
3186 }
3187 }
3188 }
3189 }
3190 } 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)) {
3191 match safety {
3192 Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
3193 Safety::Safe(sp) => {
3194 recover_safety = Safety::Unsafe(self.token.span);
3195 Some(WrongKw::Misplaced(sp))
3196 }
3197 Safety::Default => {
3198 recover_safety = Safety::Unsafe(self.token.span);
3199 Some(WrongKw::Misplaced(ext_start_sp))
3200 }
3201 }
3202 } 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)) {
3203 match safety {
3204 Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
3205 Safety::Unsafe(sp) => {
3206 recover_safety = Safety::Safe(self.token.span);
3207 Some(WrongKw::Misplaced(sp))
3208 }
3209 Safety::Default => {
3210 recover_safety = Safety::Safe(self.token.span);
3211 Some(WrongKw::Misplaced(ext_start_sp))
3212 }
3213 }
3214 } else {
3215 None
3216 };
3217
3218 if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw {
3220 let original_kw = self
3221 .span_to_snippet(original_sp)
3222 .expect("Span extracted directly from keyword should always work");
3223
3224 err.span_suggestion(
3225 self.token_uninterpolated_span(),
3226 ::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"),
3227 "",
3228 Applicability::MachineApplicable,
3229 )
3230 .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"));
3231 }
3232 else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
3234 let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
3235 if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
3236 let misplaced_qual_sp = self.token_uninterpolated_span();
3237 let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
3238
3239 err.span_suggestion(
3240 correct_pos_sp.to(misplaced_qual_sp),
3241 ::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}`"),
3242 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", misplaced_qual,
current_qual))
})format!("{misplaced_qual} {current_qual}"),
3243 Applicability::MachineApplicable,
3244 ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
3245 }
3246 }
3247 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)) {
3249 let sp = sp_start.to(self.prev_token.span);
3250 if let Ok(snippet) = self.span_to_snippet(sp) {
3251 let current_vis = match self.parse_visibility(FollowedByType::No) {
3252 Ok(v) => v,
3253 Err(d) => {
3254 d.cancel();
3255 return Err(err);
3256 }
3257 };
3258 let vs = pprust::vis_to_string(¤t_vis);
3259 let vs = vs.trim_end();
3260
3261 if #[allow(non_exhaustive_omitted_patterns)] match orig_vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(orig_vis.kind, VisibilityKind::Inherited) {
3263 err.span_suggestion(
3264 sp_start.to(self.prev_token.span),
3265 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("visibility `{0}` must come before `{1}`",
vs, snippet))
})format!("visibility `{vs}` must come before `{snippet}`"),
3266 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", vs, snippet))
})format!("{vs} {snippet}"),
3267 Applicability::MachineApplicable,
3268 );
3269 }
3270 else {
3272 err.span_suggestion(
3273 current_vis.span,
3274 "there is already a visibility modifier, remove one",
3275 "",
3276 Applicability::MachineApplicable,
3277 )
3278 .span_note(orig_vis.span, "explicit visibility first seen here");
3279 }
3280 }
3281 }
3282
3283 if let Some(wrong_kw) = wrong_kw
3286 && self.may_recover()
3287 && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
3288 {
3289 self.bump();
3291 self.bump();
3292 if #[allow(non_exhaustive_omitted_patterns)] match wrong_kw {
WrongKw::MisplacedDisallowedQualifier => true,
_ => false,
}matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
3295 err.cancel();
3296 } else {
3297 err.emit();
3298 }
3299 return Ok(FnHeader {
3300 constness: recover_constness,
3301 safety: recover_safety,
3302 coroutine_kind: recover_coroutine_kind,
3303 ext,
3304 });
3305 }
3306
3307 return Err(err);
3308 }
3309 }
3310 }
3311
3312 Ok(FnHeader { constness, safety, coroutine_kind, ext })
3313 }
3314
3315 pub(super) fn parse_fn_decl(
3317 &mut self,
3318 fn_parse_mode: &FnParseMode,
3319 ret_allow_plus: AllowPlus,
3320 recover_return_sign: RecoverReturnSign,
3321 ) -> PResult<'a, Box<FnDecl>> {
3322 Ok(Box::new(FnDecl {
3323 inputs: self.parse_fn_params(fn_parse_mode)?,
3324 output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
3325 }))
3326 }
3327
3328 pub(super) fn parse_fn_params(
3330 &mut self,
3331 fn_parse_mode: &FnParseMode,
3332 ) -> PResult<'a, ThinVec<Param>> {
3333 let mut first_param = true;
3334 if self.token != TokenKind::OpenParen
3336 && !self.token.is_keyword(kw::For)
3338 {
3339 self.dcx()
3341 .emit_err(errors::MissingFnParams { span: self.prev_token.span.shrink_to_hi() });
3342 return Ok(ThinVec::new());
3343 }
3344
3345 let (mut params, _) = self.parse_paren_comma_seq(|p| {
3346 p.recover_vcs_conflict_marker();
3347 let snapshot = p.create_snapshot_for_diagnostic();
3348 let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| {
3349 let guar = e.emit();
3350 let lo = if let TokenKind::OpenParen = p.prev_token.kind {
3354 p.prev_token.span.shrink_to_hi()
3355 } else {
3356 p.prev_token.span
3357 };
3358 p.restore_snapshot(snapshot);
3359 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)]);
3361 Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
3363 });
3364 first_param = false;
3366 param
3367 })?;
3368 self.deduplicate_recovered_params_names(&mut params);
3370 Ok(params)
3371 }
3372
3373 pub(super) fn parse_param_general(
3378 &mut self,
3379 fn_parse_mode: &FnParseMode,
3380 first_param: bool,
3381 recover_arg_parse: bool,
3382 ) -> PResult<'a, Param> {
3383 let lo = self.token.span;
3384 let attrs = self.parse_outer_attributes()?;
3385 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3386 if let Some(mut param) = this.parse_self_param()? {
3388 param.attrs = attrs;
3389 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
3390 return Ok((res?, Trailing::No, UsePreAttrPos::No));
3391 }
3392
3393 let is_dot_dot_dot = if this.token.kind == token::DotDotDot {
3394 IsDotDotDot::Yes
3395 } else {
3396 IsDotDotDot::No
3397 };
3398 let is_name_required = (fn_parse_mode.req_name)(
3399 this.token.span.with_neighbor(this.prev_token.span).edition(),
3400 is_dot_dot_dot,
3401 );
3402 let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes {
3403 this.psess.buffer_lint(
3404 VARARGS_WITHOUT_PATTERN,
3405 this.token.span,
3406 ast::CRATE_NODE_ID,
3407 errors::VarargsWithoutPattern { span: this.token.span },
3408 );
3409 false
3410 } else {
3411 is_name_required
3412 };
3413 let (pat, ty) = if is_name_required || this.is_named_param() {
3414 {
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:3414",
"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(3414u32),
::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);
3415 let (pat, colon) = this.parse_fn_param_pat_colon()?;
3416 if !colon {
3417 let mut err = this.unexpected().unwrap_err();
3418 return if let Some(ident) = this.parameter_without_type(
3419 &mut err,
3420 pat,
3421 is_name_required,
3422 first_param,
3423 fn_parse_mode,
3424 ) {
3425 let guar = err.emit();
3426 Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No))
3427 } else {
3428 Err(err)
3429 };
3430 }
3431
3432 this.eat_incorrect_doc_comment_for_param_type();
3433 (pat, this.parse_ty_for_param()?)
3434 } else {
3435 {
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:3435",
"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(3435u32),
::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");
3436 let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
3437 this.eat_incorrect_doc_comment_for_param_type();
3438 let mut ty = this.parse_ty_for_param();
3439
3440 if let Ok(t) = &ty {
3441 if let TyKind::Path(_, Path { segments, .. }) = &t.kind
3443 && let Some(segment) = segments.last()
3444 && let Some(guar) =
3445 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)])
3446 {
3447 return Ok((
3448 dummy_arg(segment.ident, guar),
3449 Trailing::No,
3450 UsePreAttrPos::No,
3451 ));
3452 }
3453
3454 if this.token != token::Comma && this.token != token::CloseParen {
3455 ty = this.unexpected_any();
3458 }
3459 }
3460 match ty {
3461 Ok(ty) => {
3462 let pat = this.mk_pat(ty.span, PatKind::Missing);
3463 (Box::new(pat), ty)
3464 }
3465 Err(err) if this.token == token::DotDotDot => return Err(err),
3467 Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
3468 Err(err) if recover_arg_parse => {
3469 err.cancel();
3471 this.restore_snapshot(parser_snapshot_before_ty);
3472 this.recover_arg_parse()?
3473 }
3474 Err(err) => return Err(err),
3475 }
3476 };
3477
3478 let span = lo.to(this.prev_token.span);
3479
3480 Ok((
3481 Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
3482 Trailing::No,
3483 UsePreAttrPos::No,
3484 ))
3485 })
3486 }
3487
3488 fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
3490 let expect_self_ident = |this: &mut Self| match this.token.ident() {
3492 Some((ident, IdentIsRaw::No)) => {
3493 this.bump();
3494 ident
3495 }
3496 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3497 };
3498 let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime());
3500 let is_isolated_self = |this: &Self, n| {
3502 this.is_keyword_ahead(n, &[kw::SelfLower])
3503 && this.look_ahead(n + 1, |t| t != &token::PathSep)
3504 };
3505 let is_isolated_pin_const_self = |this: &Self, n| {
3507 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3508 && this.is_keyword_ahead(n + 1, &[kw::Const])
3509 && is_isolated_self(this, n + 2)
3510 };
3511 let is_isolated_mut_self =
3513 |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
3514 let is_isolated_pin_mut_self = |this: &Self, n| {
3516 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3517 && is_isolated_mut_self(this, n + 1)
3518 };
3519 let parse_self_possibly_typed = |this: &mut Self, m| {
3521 let eself_ident = expect_self_ident(this);
3522 let eself_hi = this.prev_token.span;
3523 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)) {
3524 SelfKind::Explicit(this.parse_ty()?, m)
3525 } else {
3526 SelfKind::Value(m)
3527 };
3528 Ok((eself, eself_ident, eself_hi))
3529 };
3530 let expect_self_ident_not_typed =
3531 |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
3532 let eself_ident = expect_self_ident(this);
3533
3534 if this.may_recover() && this.eat_noexpect(&token::Colon) {
3536 let snap = this.create_snapshot_for_diagnostic();
3537 match this.parse_ty() {
3538 Ok(ty) => {
3539 this.dcx().emit_err(errors::IncorrectTypeOnSelf {
3540 span: ty.span,
3541 move_self_modifier: errors::MoveSelfModifier {
3542 removal_span: modifier_span,
3543 insertion_span: ty.span.shrink_to_lo(),
3544 modifier: modifier.to_ref_suggestion(),
3545 },
3546 });
3547 }
3548 Err(diag) => {
3549 diag.cancel();
3550 this.restore_snapshot(snap);
3551 }
3552 }
3553 }
3554 eself_ident
3555 };
3556 let recover_self_ptr = |this: &mut Self| {
3558 this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
3559
3560 Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
3561 };
3562
3563 let eself_lo = self.token.span;
3567 let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
3568 token::And => {
3569 let has_lifetime = is_lifetime(self, 1);
3570 let skip_lifetime_count = has_lifetime as usize;
3571 let eself = if is_isolated_self(self, skip_lifetime_count + 1) {
3572 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3575 SelfKind::Region(lifetime, Mutability::Not)
3576 } else if is_isolated_mut_self(self, skip_lifetime_count + 1) {
3577 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3580 self.bump(); SelfKind::Region(lifetime, Mutability::Mut)
3582 } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) {
3583 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3586 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3587 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Not)
3590 } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) {
3591 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3594 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3595 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Mut)
3598 } else {
3599 return Ok(None);
3601 };
3602 let hi = self.token.span;
3603 let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
3604 (eself, self_ident, hi)
3605 }
3606 token::Star if is_isolated_self(self, 1) => {
3608 self.bump();
3609 recover_self_ptr(self)?
3610 }
3611 token::Star
3613 if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
3614 {
3615 self.bump();
3616 self.bump();
3617 recover_self_ptr(self)?
3618 }
3619 token::Ident(..) if is_isolated_self(self, 0) => {
3621 parse_self_possibly_typed(self, Mutability::Not)?
3622 }
3623 token::Ident(..) if is_isolated_mut_self(self, 0) => {
3625 self.bump();
3626 parse_self_possibly_typed(self, Mutability::Mut)?
3627 }
3628 _ => return Ok(None),
3629 };
3630
3631 let eself = respan(eself_lo.to(eself_hi), eself);
3632 Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
3633 }
3634
3635 fn is_named_param(&self) -> bool {
3636 let offset = match &self.token.kind {
3637 token::OpenInvisible(origin) => match origin {
3638 InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
3639 return self.check_noexpect_past_close_delim(&token::Colon);
3640 }
3641 _ => 0,
3642 },
3643 token::And | token::AndAnd => 1,
3644 _ if self.token.is_keyword(kw::Mut) => 1,
3645 _ => 0,
3646 };
3647
3648 self.look_ahead(offset, |t| t.is_ident())
3649 && self.look_ahead(offset + 1, |t| t == &token::Colon)
3650 }
3651
3652 fn recover_self_param(&mut self) -> bool {
3653 #[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!(
3654 self.parse_outer_attributes()
3655 .and_then(|_| self.parse_self_param())
3656 .map_err(|e| e.cancel()),
3657 Ok(Some(_))
3658 )
3659 }
3660
3661 fn try_recover_const_missing_semi(
3669 &mut self,
3670 rhs: &ConstItemRhsKind,
3671 const_span: Span,
3672 ) -> Option<Box<Expr>> {
3673 if self.token == TokenKind::Semi {
3674 return None;
3675 }
3676 let ConstItemRhsKind::Body { rhs: Some(rhs) } = rhs else {
3677 return None;
3678 };
3679 if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
3680 return None;
3681 }
3682 if let Some((span, guar)) =
3683 self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
3684 {
3685 self.fn_body_missing_semi_guar = Some(guar);
3686 Some(self.mk_expr(span, ExprKind::Err(guar)))
3687 } else {
3688 None
3689 }
3690 }
3691}
3692
3693enum IsMacroRulesItem {
3694 Yes { has_bang: bool },
3695 No,
3696}
3697
3698#[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)]
3699pub(super) enum FrontMatterParsingMode {
3700 Function,
3702 FunctionPtrType,
3705}