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::diagnostics::{
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(diagnostics::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(diagnostics::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(diagnostics::DefaultNotFollowedByItem { span });
220 } else if let Defaultness::Final(span) = def {
221 this.dcx().emit_err(diagnostics::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(diagnostics::InappropriateDefault {
236 span,
237 article: kind.article(),
238 descr: kind.descr(),
239 });
240 }
241 Defaultness::Final(span) => {
242 self.dcx().emit_err(diagnostics::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(diagnostics::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(diagnostics::MissingKeywordForItemDefinition::EnumOrStruct { span })
514 } else if self.look_ahead(2, |t| *t == token::Colon)
515 || self.look_ahead(3, |t| *t == token::Colon)
516 {
517 Some(diagnostics::MissingKeywordForItemDefinition::Struct {
519 span,
520 insert_span,
521 ident,
522 })
523 } else {
524 Some(diagnostics::MissingKeywordForItemDefinition::Enum {
525 span,
526 insert_span,
527 ident,
528 })
529 }
530 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
531 self.bump(); let is_method = self.recover_self_param();
534
535 self.consume_block(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen), ConsumeClosingDelim::Yes);
536
537 let err = if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::RArrow,
token_type: crate::parser::token_type::TokenType::RArrow,
}exp!(RArrow)) || self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
538 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)]);
539 self.bump(); self.consume_block(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), ConsumeClosingDelim::Yes);
541 if is_method {
542 diagnostics::MissingKeywordForItemDefinition::Method {
543 span,
544 insert_span,
545 ident,
546 }
547 } else {
548 diagnostics::MissingKeywordForItemDefinition::Function {
549 span,
550 insert_span,
551 ident,
552 }
553 }
554 } else if is_pub && self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
555 diagnostics::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
556 } else {
557 diagnostics::MissingKeywordForItemDefinition::Ambiguous {
558 span,
559 subdiag: if found_generics {
560 None
561 } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
562 Some(diagnostics::AmbiguousMissingKwForItemSub::SuggestMacro {
563 span: ident_span,
564 snippet,
565 })
566 } else {
567 Some(diagnostics::AmbiguousMissingKwForItemSub::HelpMacro)
568 },
569 }
570 };
571 Some(err)
572 } else if found_generics {
573 Some(diagnostics::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
574 } else {
575 None
576 };
577
578 if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
579 }
580
581 fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
582 Ok(None)
584 }
585
586 fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
588 let path = self.parse_path(PathStyle::Mod)?; self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; match self.parse_delim_args() {
591 Ok(args) => {
593 self.eat_semi_for_macro_if_needed(&args, Some(&path));
594 self.complain_if_pub_macro(vis, false);
595 Ok(MacCall { path, args })
596 }
597
598 Err(mut err) => {
599 if self.token.is_ident()
601 && let [segment] = path.segments.as_slice()
602 && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
603 {
604 err.span_suggestion(
605 path.span,
606 "perhaps you meant to define a macro",
607 "macro_rules",
608 Applicability::MachineApplicable,
609 );
610 }
611 Err(err)
612 }
613 }
614 }
615
616 fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
618 let ([start @ end] | [start, .., end]) = attrs else {
619 return Ok(());
620 };
621 let msg = if end.is_doc_comment() {
622 "expected item after doc comment"
623 } else {
624 "expected item after attributes"
625 };
626 let mut err = self.dcx().struct_span_err(end.span, msg);
627 if end.is_doc_comment() {
628 err.span_label(end.span, "this doc comment doesn't document anything");
629 } else if self.token == TokenKind::Semi {
630 err.span_suggestion_verbose(
631 self.token.span,
632 "consider removing this semicolon",
633 "",
634 Applicability::MaybeIncorrect,
635 );
636 }
637 if let [.., penultimate, _] = attrs {
638 err.span_label(start.span.to(penultimate.span), "other attributes here");
639 }
640 Err(err)
641 }
642
643 fn is_async_fn(&self) -> bool {
644 self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
645 }
646
647 fn parse_polarity(&mut self) -> ast::ImplPolarity {
648 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()) {
650 self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
651 self.bump(); ast::ImplPolarity::Negative(self.prev_token.span)
653 } else {
654 ast::ImplPolarity::Positive
655 }
656 }
657
658 fn parse_item_impl(
673 &mut self,
674 attrs: &mut AttrVec,
675 defaultness: Defaultness,
676 is_reuse: bool,
677 ) -> PResult<'a, ItemKind> {
678 let constness = self.parse_constness(Case::Sensitive);
679 let safety = self.parse_safety(Case::Sensitive);
680 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
681 let mut generics_snapshot = None;
682 let mut generics = if self.choose_generics_over_qpath(0) {
684 self.parse_generics()?
685 } else {
686 if self.look_ahead(0, |t| t == &token::Lt)
689 && self.look_ahead(1, |t| t.is_ident())
690 && self.look_ahead(2, |t| t == &token::Lt)
691 {
692 generics_snapshot = Some(self.create_snapshot_for_diagnostic());
693 }
694
695 let mut generics = Generics::default();
696 generics.span = self.prev_token.span.shrink_to_hi();
699 generics
700 };
701
702 if let Const::Yes(span) = constness {
703 self.psess.gated_spans.gate(sym::const_trait_impl, span);
704 }
705
706 if (self.token_uninterpolated_span().at_least_rust_2018()
708 && self.token.is_keyword(kw::Async))
709 || self.is_kw_followed_by_ident(kw::Async)
710 {
711 self.bump();
712 self.dcx().emit_err(diagnostics::AsyncImpl { span: self.prev_token.span });
713 }
714
715 let polarity = self.parse_polarity();
716
717 let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
719 {
720 let span = self.prev_token.span.between(self.token.span);
721 return Err(self.dcx().create_err(diagnostics::MissingTraitInTraitImpl {
722 span,
723 for_span: span.to(self.token.span),
724 }));
725 } else {
726 self.parse_ty_with_generics_recovery(&generics).map_err(|e| {
727 let Some(mut snapshot) = generics_snapshot else {
728 return e;
729 };
730 snapshot.maybe_type_in_generic_parameter(e)
731 })?
732 };
733 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));
735 let missing_for_span = self.prev_token.span.between(self.token.span);
736
737 let ty_second = if self.token == token::DotDot {
738 self.bump(); Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
745 } else if has_for || self.token.can_begin_type() {
746 Some(self.parse_ty()?)
747 } else {
748 None
749 };
750
751 generics.where_clause = self.parse_where_clause()?;
752
753 let impl_items = if is_reuse {
754 Default::default()
755 } else {
756 self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
757 };
758
759 let (of_trait, self_ty) = match ty_second {
760 Some(ty_second) => {
761 if !has_for {
763 self.dcx()
764 .emit_err(diagnostics::MissingForInTraitImpl { span: missing_for_span });
765 }
766
767 let ty_first = *ty_first;
768 let path = match ty_first.kind {
769 TyKind::Path(None, path) => path,
771 other => {
772 if let TyKind::ImplTrait(_, bounds) = other
773 && let [bound] = bounds.as_slice()
774 && let GenericBound::Trait(poly_trait_ref) = bound
775 {
776 let extra_impl_kw = ty_first.span.until(bound.span());
780 self.dcx().emit_err(diagnostics::ExtraImplKeywordInTraitImpl {
781 extra_impl_kw,
782 impl_trait_span: ty_first.span,
783 });
784 poly_trait_ref.trait_ref.path.clone()
785 } else {
786 return Err(self.dcx().create_err(
787 diagnostics::ExpectedTraitInTraitImplFoundType {
788 span: ty_first.span,
789 },
790 ));
791 }
792 }
793 };
794 let trait_ref = TraitRef { path, ref_id: ty_first.id };
795
796 let of_trait =
797 Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
798 (of_trait, ty_second)
799 }
800 None => {
801 let self_ty = ty_first;
802 let error = |modifier, modifier_name, modifier_span| {
803 self.dcx().create_err(diagnostics::TraitImplModifierInInherentImpl {
804 span: self_ty.span,
805 modifier,
806 modifier_name,
807 modifier_span,
808 self_ty: self_ty.span,
809 })
810 };
811
812 if let Safety::Unsafe(span) = safety {
813 error("unsafe", "unsafe", span).with_code(E0197).emit();
814 }
815 if let ImplPolarity::Negative(span) = polarity {
816 error("!", "negative", span).emit();
817 }
818 if let Defaultness::Default(def_span) = defaultness {
819 error("default", "default", def_span).emit();
820 }
821 if let Const::Yes(span) = constness {
822 self.psess.gated_spans.gate(sym::const_trait_impl, span);
823 }
824 (None, self_ty)
825 }
826 };
827
828 Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
829 }
830
831 fn parse_item_delegation(
832 &mut self,
833 attrs: &mut AttrVec,
834 defaultness: Defaultness,
835 kind: ReuseKind,
836 ) -> PResult<'a, ItemKind> {
837 let span = self.token.span;
838 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Reuse,
token_type: crate::parser::token_type::TokenType::KwReuse,
}exp!(Reuse))?;
839
840 let item_kind = match kind {
841 ReuseKind::Path => self.parse_path_like_delegation(),
842 ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
843 }?;
844
845 self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
846
847 Ok(item_kind)
848 }
849
850 fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
851 Ok(if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
852 Some(self.parse_block()?)
853 } else {
854 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))?;
855 None
856 })
857 }
858
859 fn parse_impl_delegation(
860 &mut self,
861 span: Span,
862 attrs: &mut AttrVec,
863 defaultness: Defaultness,
864 ) -> PResult<'a, ItemKind> {
865 let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
866 let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
867
868 let until_expr_span = span.to(self.prev_token.span);
869
870 let Some(of_trait) = of_trait else {
871 return Err(self
872 .dcx()
873 .create_err(diagnostics::ImplReuseInherentImpl { span: until_expr_span }));
874 };
875
876 let body = self.parse_delegation_body()?;
877 let whole_reuse_span = span.to(self.prev_token.span);
878
879 items.push(Box::new(AssocItem {
880 id: DUMMY_NODE_ID,
881 attrs: Default::default(),
882 span: whole_reuse_span,
883 tokens: None,
884 vis: Visibility { kind: VisibilityKind::Inherited, span: whole_reuse_span },
885 kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
886 qself: None,
887 prefix: of_trait.trait_ref.path.clone(),
888 suffixes: DelegationSuffixes::Glob(whole_reuse_span),
889 body,
890 })),
891 }));
892
893 Ok(impl_item)
894 }
895
896 fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
897 let (qself, path) = if self.eat_lt() {
898 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
899 (Some(qself), path)
900 } else {
901 (None, self.parse_path(PathStyle::Expr)?)
902 };
903
904 let rename = |this: &mut Self| {
905 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 })
906 };
907
908 Ok(if self.eat_path_sep() {
909 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)) {
910 DelegationSuffixes::Glob(self.prev_token.span)
911 } else {
912 let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
913 DelegationSuffixes::List(
914 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,
915 )
916 };
917
918 ItemKind::DelegationMac(Box::new(DelegationMac {
919 qself,
920 prefix: path,
921 suffixes,
922 body: self.parse_delegation_body()?,
923 }))
924 } else {
925 let rename = rename(self)?;
926 let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
927
928 ItemKind::Delegation(Box::new(Delegation {
929 id: DUMMY_NODE_ID,
930 qself,
931 path,
932 ident,
933 rename,
934 body: self.parse_delegation_body()?,
935 source: DelegationSource::Single,
936 }))
937 })
938 }
939
940 fn parse_item_list<T>(
941 &mut self,
942 attrs: &mut AttrVec,
943 mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
944 ) -> PResult<'a, ThinVec<T>> {
945 let open_brace_span = self.token.span;
946
947 if self.token == TokenKind::Semi {
949 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
950 self.bump();
951 return Ok(ThinVec::new());
952 }
953
954 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
955 attrs.extend(self.parse_inner_attributes()?);
956
957 let mut items = ThinVec::new();
958 while !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)) {
959 if self.recover_doc_comment_before_brace() {
960 continue;
961 }
962 self.recover_vcs_conflict_marker();
963 match parse_item(self) {
964 Ok(None) => {
965 let mut is_unnecessary_semicolon = !items.is_empty()
966 && self
984 .span_to_snippet(self.prev_token.span)
985 .is_ok_and(|snippet| snippet == "}")
986 && self.token == token::Semi;
987 let mut semicolon_span = self.token.span;
988 if !is_unnecessary_semicolon {
989 is_unnecessary_semicolon =
991 self.token == token::OpenBrace && self.prev_token == token::Semi;
992 semicolon_span = self.prev_token.span;
993 }
994 let non_item_span = self.token.span;
996 let is_let = self.token.is_keyword(kw::Let);
997
998 let mut err =
999 self.dcx().struct_span_err(non_item_span, "non-item in item list");
1000 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);
1001 if is_let {
1002 err.span_suggestion_verbose(
1003 non_item_span,
1004 "consider using `const` instead of `let` for associated const",
1005 "const",
1006 Applicability::MachineApplicable,
1007 );
1008 } else {
1009 err.span_label(open_brace_span, "item list starts here")
1010 .span_label(non_item_span, "non-item starts here")
1011 .span_label(self.prev_token.span, "item list ends here");
1012 }
1013 if is_unnecessary_semicolon {
1014 err.span_suggestion(
1015 semicolon_span,
1016 "consider removing this semicolon",
1017 "",
1018 Applicability::MaybeIncorrect,
1019 );
1020 }
1021 err.emit();
1022 break;
1023 }
1024 Ok(Some(item)) => items.extend(item),
1025 Err(err) => {
1026 self.consume_block(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace), crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace), ConsumeClosingDelim::Yes);
1027 err.with_span_label(
1028 open_brace_span,
1029 "while parsing this item list starting here",
1030 )
1031 .with_span_label(self.prev_token.span, "the item list ends here")
1032 .emit();
1033 break;
1034 }
1035 }
1036 }
1037 Ok(items)
1038 }
1039
1040 fn recover_doc_comment_before_brace(&mut self) -> bool {
1042 if let token::DocComment(..) = self.token.kind {
1043 if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
1044 {
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!(
1046 self.dcx(),
1047 self.token.span,
1048 E0584,
1049 "found a documentation comment that doesn't document anything",
1050 )
1051 .with_span_label(self.token.span, "this doc comment doesn't document anything")
1052 .with_help(
1053 "doc comments must come before what they document, if a comment was \
1054 intended use `//`",
1055 )
1056 .emit();
1057 self.bump();
1058 return true;
1059 }
1060 }
1061 false
1062 }
1063
1064 fn parse_defaultness(&mut self) -> Defaultness {
1066 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))
1070 && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
1071 {
1072 self.psess.gated_spans.gate(sym::specialization, self.token.span);
1073 self.bump(); Defaultness::Default(self.prev_token_uninterpolated_span())
1075 } 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)) {
1076 self.psess.gated_spans.gate(sym::final_associated_functions, self.prev_token.span);
1077 Defaultness::Final(self.prev_token_uninterpolated_span())
1078 } else {
1079 Defaultness::Implicit
1080 }
1081 }
1082
1083 fn check_trait_front_matter(&mut self) -> bool {
1085 const SUFFIXES: &[&[Symbol]] = &[
1086 &[kw::Trait],
1087 &[kw::Auto, kw::Trait],
1088 &[kw::Unsafe, kw::Trait],
1089 &[kw::Unsafe, kw::Auto, kw::Trait],
1090 &[kw::Const, kw::Trait],
1091 &[kw::Const, kw::Auto, kw::Trait],
1092 &[kw::Const, kw::Unsafe, kw::Trait],
1093 &[kw::Const, kw::Unsafe, kw::Auto, kw::Trait],
1094 ];
1095 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) {
1097 if self.is_keyword_ahead(2, &[kw::In]) {
1099 return true;
1100 }
1101 if self.is_keyword_ahead(2, &[kw::Crate, kw::SelfLower, kw::Super])
1103 && self.look_ahead(3, |t| t == &token::CloseParen)
1104 && SUFFIXES.iter().any(|suffix| {
1105 suffix.iter().enumerate().all(|(i, kw)| self.is_keyword_ahead(i + 4, &[*kw]))
1106 })
1107 {
1108 return true;
1109 }
1110 SUFFIXES.iter().any(|suffix| {
1112 suffix.iter().enumerate().all(|(i, kw)| {
1113 self.tree_look_ahead(i + 2, |t| {
1114 if let TokenTree::Token(token, _) = t {
1115 token.is_keyword(*kw)
1116 } else {
1117 false
1118 }
1119 })
1120 .unwrap_or(false)
1121 })
1122 })
1123 } else {
1124 SUFFIXES.iter().any(|suffix| {
1125 suffix.iter().enumerate().all(|(i, kw)| {
1126 if i == 0 {
1128 match *kw {
1129 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)),
1130 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)),
1131 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)),
1132 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)),
1133 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1134 }
1135 } else {
1136 self.is_keyword_ahead(i, &[*kw])
1137 }
1138 })
1139 })
1140 }
1141 }
1142
1143 fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
1145 let impl_restriction = self.parse_impl_restriction()?;
1146 let constness = self.parse_constness(Case::Sensitive);
1147 if let Const::Yes(span) = constness {
1148 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1149 }
1150 let safety = self.parse_safety(Case::Sensitive);
1151 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)) {
1153 self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
1154 IsAuto::Yes
1155 } else {
1156 IsAuto::No
1157 };
1158
1159 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait))?;
1160 let ident = self.parse_ident()?;
1161 let mut generics = self.parse_generics()?;
1162
1163 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));
1165 let span_at_colon = self.prev_token.span;
1166 let bounds = if had_colon { self.parse_generic_bounds()? } else { ThinVec::new() };
1167
1168 let span_before_eq = self.prev_token.span;
1169 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1170 if had_colon {
1172 let span = span_at_colon.to(span_before_eq);
1173 self.dcx().emit_err(diagnostics::BoundsNotAllowedOnTraitAliases { span });
1174 }
1175
1176 let bounds = self.parse_generic_bounds()?;
1177 generics.where_clause = self.parse_where_clause()?;
1178 self.expect_semi()?;
1179
1180 let whole_span = lo.to(self.prev_token.span);
1181 if is_auto == IsAuto::Yes {
1182 self.dcx().emit_err(diagnostics::TraitAliasCannotBeAuto { span: whole_span });
1183 }
1184 if let Safety::Unsafe(_) = safety {
1185 self.dcx().emit_err(diagnostics::TraitAliasCannotBeUnsafe { span: whole_span });
1186 }
1187 if let RestrictionKind::Restricted { .. } = impl_restriction.kind {
1188 self.dcx()
1189 .emit_err(diagnostics::TraitAliasCannotBeImplRestricted { span: whole_span });
1190 }
1191
1192 self.psess.gated_spans.gate(sym::trait_alias, whole_span);
1193
1194 Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
1195 } else {
1196 generics.where_clause = self.parse_where_clause()?;
1198 let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
1199 Ok(ItemKind::Trait(Box::new(Trait {
1200 impl_restriction,
1201 constness,
1202 is_auto,
1203 safety,
1204 ident,
1205 generics,
1206 bounds,
1207 items,
1208 })))
1209 }
1210 }
1211
1212 pub fn parse_impl_item(
1213 &mut self,
1214 force_collect: ForceCollect,
1215 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1216 let fn_parse_mode =
1217 FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
1218 self.parse_assoc_item(fn_parse_mode, force_collect)
1219 }
1220
1221 pub fn parse_trait_item(
1222 &mut self,
1223 force_collect: ForceCollect,
1224 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1225 let fn_parse_mode = FnParseMode {
1226 req_name: |edition, _| edition >= Edition::Edition2018,
1227 context: FnContext::Trait,
1228 req_body: false,
1229 };
1230 self.parse_assoc_item(fn_parse_mode, force_collect)
1231 }
1232
1233 fn parse_assoc_item(
1235 &mut self,
1236 fn_parse_mode: FnParseMode,
1237 force_collect: ForceCollect,
1238 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1239 Ok(self
1240 .parse_item_(
1241 fn_parse_mode,
1242 force_collect,
1243 AllowConstBlockItems::DoesNotMatter, )?
1245 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1246 let kind = match AssocItemKind::try_from(kind) {
1247 Ok(kind) => kind,
1248 Err(kind) => match kind {
1249 ItemKind::Static(StaticItem {
1250 ident,
1251 ty,
1252 safety: _,
1253 mutability: _,
1254 expr,
1255 define_opaque,
1256 eii_impls: _,
1257 }) => {
1258 self.dcx()
1259 .emit_err(diagnostics::AssociatedStaticItemNotAllowed { span });
1260 AssocItemKind::Const(Box::new(ConstItem {
1261 defaultness: Defaultness::Implicit,
1262 ident,
1263 generics: Generics::default(),
1264 ty,
1265 rhs_kind: ConstItemRhsKind::Body { rhs: expr },
1266 define_opaque,
1267 }))
1268 }
1269 _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
1270 },
1271 };
1272 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1273 }))
1274 }
1275
1276 fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
1282 let ident = self.parse_ident()?;
1283 let mut generics = self.parse_generics()?;
1284
1285 let bounds =
1287 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) { self.parse_generic_bounds()? } else { ThinVec::new() };
1288 generics.where_clause = self.parse_where_clause()?;
1289
1290 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 };
1291
1292 let after_where_clause = self.parse_where_clause()?;
1293
1294 self.expect_semi()?;
1295
1296 Ok(ItemKind::TyAlias(Box::new(TyAlias {
1297 defaultness,
1298 ident,
1299 generics,
1300 after_where_clause,
1301 bounds,
1302 ty,
1303 })))
1304 }
1305
1306 fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
1316 let lo = self.token.span;
1317
1318 let mut prefix = ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo() };
1319 let kind =
1320 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() {
1321 let mod_sep_ctxt = self.token.span.ctxt();
1323 if self.eat_path_sep() {
1324 prefix
1325 .segments
1326 .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
1327 }
1328
1329 self.parse_use_tree_glob_or_nested()?
1330 } else {
1331 prefix = self.parse_path(PathStyle::Mod)?;
1333
1334 if self.eat_path_sep() {
1335 self.parse_use_tree_glob_or_nested()?
1336 } else {
1337 while self.eat_noexpect(&token::Colon) {
1339 self.dcx().emit_err(diagnostics::SingleColonImportPath {
1340 span: self.prev_token.span,
1341 });
1342
1343 self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
1345 prefix.span = lo.to(self.prev_token.span);
1346 }
1347
1348 UseTreeKind::Simple(self.parse_rename()?)
1349 }
1350 };
1351
1352 Ok(UseTree { prefix, kind })
1353 }
1354
1355 fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
1357 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
1358 UseTreeKind::Glob(self.prev_token.span)
1359 } else {
1360 let lo = self.token.span;
1361 UseTreeKind::Nested {
1362 items: self.parse_use_tree_list()?,
1363 span: lo.to(self.prev_token.span),
1364 }
1365 })
1366 }
1367
1368 fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
1374 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| {
1375 p.recover_vcs_conflict_marker();
1376 Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
1377 })
1378 .map(|(r, _)| r)
1379 }
1380
1381 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1382 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)) {
1383 self.parse_ident_or_underscore().map(Some)
1384 } else {
1385 Ok(None)
1386 }
1387 }
1388
1389 fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
1390 match self.token.ident() {
1391 Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
1392 self.bump();
1393 Ok(ident)
1394 }
1395 _ => self.parse_ident(),
1396 }
1397 }
1398
1399 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1408 let orig_ident = self.parse_crate_name_with_dashes()?;
1410 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1411 (Some(orig_ident.name), rename)
1412 } else {
1413 (None, orig_ident)
1414 };
1415 self.expect_semi()?;
1416 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1417 }
1418
1419 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1420 let ident = if self.token.is_keyword(kw::SelfLower) {
1421 self.parse_path_segment_ident()
1422 } else {
1423 self.parse_ident()
1424 }?;
1425
1426 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1427 if self.token != dash.tok {
1428 return Ok(ident);
1429 }
1430
1431 let mut dashes = ::alloc::vec::Vec::new()vec![];
1433 let mut idents = ::alloc::vec::Vec::new()vec![];
1434 while self.eat(dash) {
1435 dashes.push(self.prev_token.span);
1436 idents.push(self.parse_ident()?);
1437 }
1438
1439 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1440 let mut fixed_name = ident.name.to_string();
1441 for part in idents {
1442 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1443 }
1444
1445 self.dcx().emit_err(diagnostics::ExternCrateNameWithDashes {
1446 span: fixed_name_sp,
1447 sugg: diagnostics::ExternCrateNameWithDashesSugg { dashes },
1448 });
1449
1450 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1451 }
1452
1453 fn parse_item_foreign_mod(
1464 &mut self,
1465 attrs: &mut AttrVec,
1466 mut safety: Safety,
1467 ) -> PResult<'a, ItemKind> {
1468 let extern_span = self.prev_token_uninterpolated_span();
1469 let abi = self.parse_abi(); if safety == Safety::Default
1472 && self.token.is_keyword(kw::Unsafe)
1473 && self.look_ahead(1, |t| *t == token::OpenBrace)
1474 {
1475 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();
1476 safety = Safety::Unsafe(self.token.span);
1477 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));
1478 }
1479 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1480 extern_span,
1481 safety,
1482 abi,
1483 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1484 }))
1485 }
1486
1487 pub fn parse_foreign_item(
1489 &mut self,
1490 force_collect: ForceCollect,
1491 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1492 let fn_parse_mode = FnParseMode {
1493 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1494 context: FnContext::Free,
1495 req_body: false,
1496 };
1497 Ok(self
1498 .parse_item_(
1499 fn_parse_mode,
1500 force_collect,
1501 AllowConstBlockItems::DoesNotMatter, )?
1503 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1504 let kind = match ForeignItemKind::try_from(kind) {
1505 Ok(kind) => kind,
1506 Err(kind) => match kind {
1507 ItemKind::Const(ConstItem { ident, ty, rhs_kind, .. }) => {
1508 let const_span = Some(span.with_hi(ident.span.lo()))
1509 .filter(|span| span.can_be_used_for_suggestions());
1510 self.dcx().emit_err(diagnostics::ExternItemCannotBeConst {
1511 ident_span: ident.span,
1512 const_span,
1513 });
1514 ForeignItemKind::Static(Box::new(StaticItem {
1515 ident,
1516 ty,
1517 mutability: Mutability::Not,
1518 expr: match rhs_kind {
1519 ConstItemRhsKind::Body { rhs } => rhs,
1520 ConstItemRhsKind::TypeConst { rhs: Some(anon) } => {
1521 Some(anon.value)
1522 }
1523 ConstItemRhsKind::TypeConst { rhs: None } => None,
1524 },
1525 safety: Safety::Default,
1526 define_opaque: None,
1527 eii_impls: ThinVec::default(),
1528 }))
1529 }
1530 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1531 },
1532 };
1533 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1534 }))
1535 }
1536
1537 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1538 let span = self.psess.source_map().guess_head_span(span);
1540 let descr = kind.descr();
1541 let help = match kind {
1542 ItemKind::DelegationMac(DelegationMac {
1543 suffixes: DelegationSuffixes::Glob(_),
1544 ..
1545 }) => false,
1546 _ => true,
1547 };
1548 self.dcx().emit_err(diagnostics::BadItemKind { span, descr, ctx, help });
1549 None
1550 }
1551
1552 fn is_use_closure(&self) -> bool {
1553 if self.token.is_keyword(kw::Use) {
1554 self.look_ahead(1, |token| {
1556 let dist =
1558 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1559
1560 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))
1561 })
1562 } else {
1563 false
1564 }
1565 }
1566
1567 fn is_unsafe_foreign_mod(&self) -> bool {
1568 if !self.token.is_keyword(kw::Unsafe) {
1570 return false;
1571 }
1572 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1574 return false;
1575 }
1576
1577 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1579
1580 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, _)))
1585 == Some(true)
1586 }
1587
1588 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1589 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) {
1590 !self.look_ahead(1, |token| {
1592 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1593 return true;
1594 }
1595 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1596 })
1597 } else {
1598 (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)
1600 || 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))
1601 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1602 };
1603
1604 if is_global_static {
1605 let safety = self.parse_safety(case);
1606 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);
1607 Some(safety)
1608 } else {
1609 None
1610 }
1611 }
1612
1613 fn recover_const_mut(&mut self, const_span: Span) {
1615 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)) {
1616 let span = self.prev_token.span;
1617 self.dcx()
1618 .emit_err(diagnostics::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1619 } 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)) {
1620 let span = self.prev_token.span;
1621 self.dcx()
1622 .emit_err(diagnostics::ConstLetMutuallyExclusive { span: const_span.to(span) });
1623 }
1624 }
1625
1626 fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
1627 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1628 let const_span = self.prev_token.span;
1629 self.psess.gated_spans.gate(sym::const_block_items, const_span);
1630 let block = self.parse_block()?;
1631 Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
1632 }
1633
1634 fn parse_static_item(
1641 &mut self,
1642 safety: Safety,
1643 mutability: Mutability,
1644 ) -> PResult<'a, ItemKind> {
1645 let ident = self.parse_ident()?;
1646
1647 if self.token == TokenKind::Lt && self.may_recover() {
1648 let generics = self.parse_generics()?;
1649 self.dcx().emit_err(diagnostics::StaticWithGenerics { span: generics.span });
1650 }
1651
1652 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))) {
1655 (true, false) => self.parse_ty()?,
1656 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1659 };
1660
1661 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 };
1662
1663 self.expect_semi()?;
1664
1665 let item = StaticItem {
1666 ident,
1667 ty,
1668 safety,
1669 mutability,
1670 expr,
1671 define_opaque: None,
1672 eii_impls: ThinVec::default(),
1673 };
1674 Ok(ItemKind::Static(Box::new(item)))
1675 }
1676
1677 fn parse_const_item(
1686 &mut self,
1687 const_arg: bool,
1688 const_span: Span,
1689 ) -> PResult<'a, (Ident, Generics, Box<Ty>, ConstItemRhsKind)> {
1690 let ident = self.parse_ident_or_underscore()?;
1691
1692 let mut generics = self.parse_generics()?;
1693
1694 if !generics.span.is_empty() {
1697 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1698 }
1699
1700 let ty = match (
1703 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1704 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)),
1705 ) {
1706 (true, false) => self.parse_ty()?,
1707 (colon, _) => self.recover_missing_global_item_type(colon, None),
1709 };
1710
1711 let before_where_clause =
1714 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1715
1716 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) {
1717 (true, true) => {
1718 ConstItemRhsKind::TypeConst { rhs: Some(self.parse_expr_anon_const()?) }
1719 }
1720 (true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) },
1721 (false, true) => ConstItemRhsKind::TypeConst { rhs: None },
1722 (false, false) => ConstItemRhsKind::Body { rhs: None },
1723 };
1724
1725 let after_where_clause = self.parse_where_clause()?;
1726
1727 if before_where_clause.has_where_token
1731 && let Some(rhs_span) = rhs.span()
1732 {
1733 self.dcx().emit_err(diagnostics::WhereClauseBeforeConstBody {
1734 span: before_where_clause.span,
1735 name: ident.span,
1736 body: rhs_span,
1737 sugg: if !after_where_clause.has_where_token {
1738 self.psess.source_map().span_to_snippet(rhs_span).ok().map(|body_s| {
1739 diagnostics::WhereClauseBeforeConstBodySugg {
1740 left: before_where_clause.span.shrink_to_lo(),
1741 snippet: body_s,
1742 right: before_where_clause.span.shrink_to_hi().to(rhs_span),
1743 }
1744 })
1745 } else {
1746 None
1749 },
1750 });
1751 }
1752
1753 let mut predicates = before_where_clause.predicates;
1760 predicates.extend(after_where_clause.predicates);
1761 let where_clause = WhereClause {
1762 has_where_token: before_where_clause.has_where_token
1763 || after_where_clause.has_where_token,
1764 predicates,
1765 span: if after_where_clause.has_where_token {
1766 after_where_clause.span
1767 } else {
1768 before_where_clause.span
1769 },
1770 };
1771
1772 if where_clause.has_where_token {
1773 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1774 }
1775
1776 generics.where_clause = where_clause;
1777
1778 if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {
1779 return Ok((ident, generics, ty, ConstItemRhsKind::Body { rhs: Some(rhs) }));
1780 }
1781 self.expect_semi()?;
1782
1783 Ok((ident, generics, ty, rhs))
1784 }
1785
1786 fn recover_missing_global_item_type(
1789 &mut self,
1790 colon_present: bool,
1791 m: Option<Mutability>,
1792 ) -> Box<Ty> {
1793 let kind = match m {
1796 Some(Mutability::Mut) => "static mut",
1797 Some(Mutability::Not) => "static",
1798 None => "const",
1799 };
1800
1801 let colon = match colon_present {
1802 true => "",
1803 false => ":",
1804 };
1805
1806 let span = self.prev_token.span.shrink_to_hi();
1807 let err = self.dcx().create_err(diagnostics::MissingConstType { span, colon, kind });
1808 err.stash(span, StashKey::ItemNoType);
1809
1810 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID })
1813 }
1814
1815 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1817 if self.token.is_keyword(kw::Struct) {
1818 let span = self.prev_token.span.to(self.token.span);
1819 let err = diagnostics::EnumStructMutuallyExclusive { span };
1820 if self.look_ahead(1, |t| t.is_ident()) {
1821 self.bump();
1822 self.dcx().emit_err(err);
1823 } else {
1824 return Err(self.dcx().create_err(err));
1825 }
1826 }
1827
1828 let prev_span = self.prev_token.span;
1829 let ident = self.parse_ident()?;
1830 let mut generics = self.parse_generics()?;
1831 generics.where_clause = self.parse_where_clause()?;
1832
1833 let (variants, _) = if self.token == TokenKind::Semi {
1835 self.dcx().emit_err(diagnostics::UseEmptyBlockNotSemi { span: self.token.span });
1836 self.bump();
1837 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1838 } else {
1839 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| {
1840 p.parse_enum_variant(ident.span)
1841 })
1842 .map_err(|mut err| {
1843 err.span_label(ident.span, "while parsing this enum");
1844 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1846 let snapshot = self.create_snapshot_for_diagnostic();
1847 self.bump();
1848 match self.parse_ty() {
1849 Ok(_) => {
1850 err.span_suggestion_verbose(
1851 prev_span,
1852 "perhaps you meant to use `struct` here",
1853 "struct",
1854 Applicability::MaybeIncorrect,
1855 );
1856 }
1857 Err(e) => {
1858 e.cancel();
1859 }
1860 }
1861 self.restore_snapshot(snapshot);
1862 }
1863 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1864 self.bump(); err
1866 })?
1867 };
1868
1869 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1870 Ok(ItemKind::Enum(ident, generics, enum_definition))
1871 }
1872
1873 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1874 self.recover_vcs_conflict_marker();
1875 let variant_attrs = self.parse_outer_attributes()?;
1876 self.recover_vcs_conflict_marker();
1877 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1878 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1879 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1880 let vlo = this.token.span;
1881
1882 let vis = this.parse_visibility(FollowedByType::No)?;
1883 if !this.recover_nested_adt_item(kw::Enum)? {
1884 return Ok((None, Trailing::No, UsePreAttrPos::No));
1885 }
1886 let ident = this.parse_field_ident("enum", vlo)?;
1887
1888 if this.token == token::Bang {
1889 if let Err(err) = this.unexpected() {
1890 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();
1891 }
1892
1893 this.bump();
1894 this.parse_delim_args()?;
1895
1896 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1897 }
1898
1899 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)) {
1900 let (fields, recovered) =
1902 match this.parse_record_struct_body("struct", ident.span, false) {
1903 Ok((fields, recovered)) => (fields, recovered),
1904 Err(mut err) => {
1905 if this.token == token::Colon {
1906 return Err(err);
1908 }
1909 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1910 this.bump(); err.span_label(span, "while parsing this enum");
1912 err.help(help);
1913 let guar = err.emit();
1914 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1915 }
1916 };
1917 VariantData::Struct { fields, recovered }
1918 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1919 let body = match this.parse_tuple_struct_body() {
1920 Ok(body) => body,
1921 Err(mut err) => {
1922 if this.token == token::Colon {
1923 return Err(err);
1925 }
1926 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
1927 this.bump(); err.span_label(span, "while parsing this enum");
1929 err.help(help);
1930 err.emit();
1931 ::thin_vec::ThinVec::new()thin_vec![]
1932 }
1933 };
1934 VariantData::Tuple(body, DUMMY_NODE_ID)
1935 } else {
1936 VariantData::Unit(DUMMY_NODE_ID)
1937 };
1938
1939 let disr_expr =
1940 if this.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) { Some(this.parse_expr_anon_const()?) } else { None };
1941
1942 let span = vlo.to(this.prev_token.span);
1943 if ident.name == kw::Underscore {
1944 this.psess.gated_spans.gate(sym::unnamed_enum_variants, span);
1945 }
1946 let vr = ast::Variant {
1947 ident,
1948 vis,
1949 id: DUMMY_NODE_ID,
1950 attrs: variant_attrs,
1951 data: struct_def,
1952 disr_expr,
1953 span,
1954 is_placeholder: false,
1955 };
1956
1957 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
1958 })
1959 .map_err(|mut err| {
1960 err.help(help);
1961 err
1962 })
1963 }
1964
1965 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
1967 let ident = self.parse_ident()?;
1968
1969 let mut generics = self.parse_generics()?;
1970
1971 let vdata = if self.token.is_keyword(kw::Where) {
1986 let tuple_struct_body;
1987 (generics.where_clause, tuple_struct_body) =
1988 self.parse_struct_where_clause(ident, generics.span)?;
1989
1990 if let Some(body) = tuple_struct_body {
1991 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
1993 self.expect_semi()?;
1994 body
1995 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1996 VariantData::Unit(DUMMY_NODE_ID)
1998 } else {
1999 let (fields, recovered) = self.parse_record_struct_body(
2001 "struct",
2002 ident.span,
2003 generics.where_clause.has_where_token,
2004 )?;
2005 VariantData::Struct { fields, recovered }
2006 }
2007 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
2009 VariantData::Unit(DUMMY_NODE_ID)
2010 } else if self.token == token::OpenBrace {
2012 let (fields, recovered) = self.parse_record_struct_body(
2013 "struct",
2014 ident.span,
2015 generics.where_clause.has_where_token,
2016 )?;
2017 VariantData::Struct { fields, recovered }
2018 } else if self.token == token::OpenParen {
2020 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
2021 generics.where_clause = self.parse_where_clause()?;
2022 self.expect_semi()?;
2023 body
2024 } else {
2025 let err = diagnostics::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
2026 return Err(self.dcx().create_err(err));
2027 };
2028
2029 Ok(ItemKind::Struct(ident, generics, vdata))
2030 }
2031
2032 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
2034 let ident = self.parse_ident()?;
2035
2036 let mut generics = self.parse_generics()?;
2037
2038 let vdata = if self.token.is_keyword(kw::Where) {
2039 generics.where_clause = self.parse_where_clause()?;
2040 let (fields, recovered) = self.parse_record_struct_body(
2041 "union",
2042 ident.span,
2043 generics.where_clause.has_where_token,
2044 )?;
2045 VariantData::Struct { fields, recovered }
2046 } else if self.token == token::OpenBrace {
2047 let (fields, recovered) = self.parse_record_struct_body(
2048 "union",
2049 ident.span,
2050 generics.where_clause.has_where_token,
2051 )?;
2052 VariantData::Struct { fields, recovered }
2053 } else {
2054 let token_str = super::token_descr(&self.token);
2055 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}");
2056 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2057 err.span_label(self.token.span, "expected `where` or `{` after union name");
2058 return Err(err);
2059 };
2060
2061 Ok(ItemKind::Union(ident, generics, vdata))
2062 }
2063
2064 pub(crate) fn parse_record_struct_body(
2069 &mut self,
2070 adt_ty: &str,
2071 ident_span: Span,
2072 parsed_where: bool,
2073 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
2074 let mut fields = ThinVec::new();
2075 let mut recovered = Recovered::No;
2076 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2077 while self.token != token::CloseBrace {
2078 match self.parse_field_def(adt_ty, ident_span) {
2079 Ok(field) => {
2080 fields.push(field);
2081 }
2082 Err(mut err) => {
2083 self.consume_block(
2084 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
2085 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
2086 ConsumeClosingDelim::No,
2087 );
2088 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}"));
2089 let guar = err.emit();
2090 recovered = Recovered::Yes(guar);
2091 break;
2092 }
2093 }
2094 }
2095 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
2096 } else {
2097 let token_str = super::token_descr(&self.token);
2098 let where_str = if parsed_where { "" } else { "`where`, or " };
2099 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}");
2100 let mut err = self.dcx().struct_span_err(self.token.span, msg);
2101 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",));
2102 return Err(err);
2103 }
2104
2105 Ok((fields, recovered))
2106 }
2107
2108 fn parse_unsafe_field(&mut self) -> Safety {
2109 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)) {
2111 let span = self.prev_token.span;
2112 self.psess.gated_spans.gate(sym::unsafe_fields, span);
2113 Safety::Unsafe(span)
2114 } else {
2115 Safety::Default
2116 }
2117 }
2118 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
2121 let openparen_span = self.token.span;
2122 let mut encountered_colon = false;
2123 self.parse_paren_comma_seq(|p| {
2124 let attrs = p.parse_outer_attributes()?;
2125 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
2126 let mut snapshot = None;
2127 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
2128 snapshot = Some(p.create_snapshot_for_diagnostic());
2132 }
2133 let lo = p.token.span;
2134 let vis = match p.parse_visibility(FollowedByType::Yes) {
2135 Ok(vis) => vis,
2136 Err(err) => {
2137 if let Some(ref mut snapshot) = snapshot {
2138 snapshot.recover_vcs_conflict_marker();
2139 }
2140 return Err(err);
2141 }
2142 };
2143 let mut_restriction = p.parse_mut_restriction()?;
2144 encountered_colon |=
2145 p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
2146 let ty = match p.parse_ty() {
2149 Ok(ty) => ty,
2150 Err(err) => {
2151 if let Some(ref mut snapshot) = snapshot {
2152 snapshot.recover_vcs_conflict_marker();
2153 }
2154 return Err(err);
2155 }
2156 };
2157 let mut default = None;
2158 if p.token == token::Eq {
2159 let mut snapshot = p.create_snapshot_for_diagnostic();
2160 snapshot.bump();
2161 match snapshot.parse_expr_anon_const() {
2162 Ok(const_expr) => {
2163 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2164 p.psess.gated_spans.gate(sym::default_field_values, sp);
2165 p.restore_snapshot(snapshot);
2166 default = Some(const_expr);
2167 }
2168 Err(err) => {
2169 err.cancel();
2170 }
2171 }
2172 }
2173
2174 Ok((
2175 FieldDef {
2176 span: lo.to(ty.span),
2177 vis,
2178 mut_restriction,
2179 safety: Safety::Default,
2180 ident: None,
2181 id: DUMMY_NODE_ID,
2182 ty,
2183 default,
2184 attrs,
2185 is_placeholder: false,
2186 },
2187 Trailing::from(p.token == token::Comma),
2188 UsePreAttrPos::No,
2189 ))
2190 })
2191 })
2192 .map(|(r, _)| r)
2193 .map_err(|mut error| {
2194 if self.token == token::Colon {
2195 error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
2196 }
2197 if encountered_colon {
2198 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
2199 self.bump();
2200 error.subdiagnostic(UseRegularStructSuggestion {
2201 open: openparen_span,
2202 close: self.prev_token.span,
2203 semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
2204 });
2205 }
2206 error
2207 })
2208 }
2209
2210 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2212 self.recover_vcs_conflict_marker();
2213 let attrs = self.parse_outer_attributes()?;
2214 self.recover_vcs_conflict_marker();
2215 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2216 let lo = this.token.span;
2217 let vis = this.parse_visibility(FollowedByType::No)?;
2218 let mut_restriction = this.parse_mut_restriction()?;
2219 let safety = this.parse_unsafe_field();
2220 this.parse_single_struct_field(
2221 adt_ty,
2222 lo,
2223 vis,
2224 mut_restriction,
2225 safety,
2226 attrs,
2227 ident_span,
2228 )
2229 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2230 })
2231 }
2232
2233 fn parse_single_struct_field(
2235 &mut self,
2236 adt_ty: &str,
2237 lo: Span,
2238 vis: Visibility,
2239 mut_restriction: MutRestriction,
2240 safety: Safety,
2241 attrs: AttrVec,
2242 ident_span: Span,
2243 ) -> PResult<'a, FieldDef> {
2244 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, mut_restriction, safety, attrs)?;
2245 match self.token.kind {
2246 token::Comma => {
2247 self.bump();
2248 }
2249 token::Semi => {
2250 self.bump();
2251 let sp = self.prev_token.span;
2252 let mut err =
2253 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 `,`"));
2254 err.span_suggestion_short(
2255 sp,
2256 "replace `;` with `,`",
2257 ",",
2258 Applicability::MachineApplicable,
2259 );
2260 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}"));
2261 err.emit();
2262 }
2263 token::CloseBrace => {}
2264 token::DocComment(..) => {
2265 let previous_span = self.prev_token.span;
2266 let mut err = diagnostics::DocCommentDoesNotDocumentAnything {
2267 span: self.token.span,
2268 missing_comma: None,
2269 };
2270 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 {
2272 self.dcx().emit_err(err);
2273 } else {
2274 let sp = previous_span.shrink_to_hi();
2275 err.missing_comma = Some(sp);
2276 return Err(self.dcx().create_err(err));
2277 }
2278 }
2279 _ => {
2280 let sp = self.prev_token.span.shrink_to_hi();
2281 let msg =
2282 ::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));
2283
2284 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2286 && let Some(last_segment) = segments.last()
2287 {
2288 let guar = self.check_trailing_angle_brackets(
2289 last_segment,
2290 &[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)],
2291 );
2292 if let Some(_guar) = guar {
2293 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2296
2297 return Ok(a_var);
2300 }
2301 }
2302
2303 let mut err = self.dcx().struct_span_err(sp, msg);
2304
2305 if self.token.is_ident()
2306 || (self.token == TokenKind::Pound
2307 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2308 {
2309 err.span_suggestion(
2312 sp,
2313 "try adding a comma",
2314 ",",
2315 Applicability::MachineApplicable,
2316 );
2317 err.emit();
2318 } else {
2319 return Err(err);
2320 }
2321 }
2322 }
2323 Ok(a_var)
2324 }
2325
2326 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2327 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)) {
2328 let sm = self.psess.source_map();
2329 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2330 let semi_typo = self.token == token::Semi
2331 && self.look_ahead(1, |t| {
2332 t.is_path_start()
2333 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2336 (Ok(l), Ok(r)) => l.line == r.line,
2337 _ => true,
2338 }
2339 });
2340 if eq_typo || semi_typo {
2341 self.bump();
2342 err.with_span_suggestion_short(
2344 self.prev_token.span,
2345 "field names and their types are separated with `:`",
2346 ":",
2347 Applicability::MachineApplicable,
2348 )
2349 .emit();
2350 } else {
2351 return Err(err);
2352 }
2353 }
2354 Ok(())
2355 }
2356
2357 fn parse_name_and_ty(
2359 &mut self,
2360 adt_ty: &str,
2361 lo: Span,
2362 vis: Visibility,
2363 mut_restriction: MutRestriction,
2364 safety: Safety,
2365 attrs: AttrVec,
2366 ) -> PResult<'a, FieldDef> {
2367 let name = self.parse_field_ident(adt_ty, lo)?;
2368 if self.token == token::Bang {
2369 if let Err(mut err) = self.unexpected() {
2370 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2372 return Err(err);
2373 }
2374 }
2375 self.expect_field_ty_separator()?;
2376 let ty = self.parse_ty()?;
2377 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2378 self.dcx()
2379 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2380 .with_span_suggestion_verbose(
2381 self.token.span,
2382 "write a path separator here",
2383 "::",
2384 Applicability::MaybeIncorrect,
2385 )
2386 .emit();
2387 }
2388 let default = if self.token == token::Eq {
2389 self.bump();
2390 let const_expr = self.parse_expr_anon_const()?;
2391 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2392 self.psess.gated_spans.gate(sym::default_field_values, sp);
2393 Some(const_expr)
2394 } else {
2395 None
2396 };
2397 Ok(FieldDef {
2398 span: lo.to(self.prev_token.span),
2399 ident: Some(name),
2400 vis,
2401 safety,
2402 mut_restriction,
2403 id: DUMMY_NODE_ID,
2404 ty,
2405 default,
2406 attrs,
2407 is_placeholder: false,
2408 })
2409 }
2410
2411 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2414 let (ident, is_raw) = self.ident_or_err(true)?;
2415 if is_raw == IdentIsRaw::No
2416 && ident.is_reserved()
2417 && !(ident.name == kw::Underscore && adt_ty == "enum")
2418 {
2419 let snapshot = self.create_snapshot_for_diagnostic();
2420 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2421 let inherited_vis = Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited };
2422 let fn_parse_mode =
2424 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2425 match self.parse_fn(
2426 &mut AttrVec::new(),
2427 fn_parse_mode,
2428 lo,
2429 &inherited_vis,
2430 Case::Insensitive,
2431 ) {
2432 Ok(_) => {
2433 self.dcx().struct_span_err(
2434 lo.to(self.prev_token.span),
2435 ::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"),
2436 )
2437 .with_help(
2438 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2439 )
2440 .with_help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information")
2441 }
2442 Err(err) => {
2443 err.cancel();
2444 self.restore_snapshot(snapshot);
2445 self.expected_ident_found_err()
2446 }
2447 }
2448 } 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)) {
2449 match self.parse_item_struct() {
2450 Ok(item) => {
2451 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2452 self.dcx()
2453 .struct_span_err(
2454 lo.with_hi(ident.span.hi()),
2455 ::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"),
2456 )
2457 .with_help(
2458 "consider creating a new `struct` definition instead of nesting",
2459 )
2460 }
2461 Err(err) => {
2462 err.cancel();
2463 self.restore_snapshot(snapshot);
2464 self.expected_ident_found_err()
2465 }
2466 }
2467 } else {
2468 let mut err = self.expected_ident_found_err();
2469 if self.eat_keyword_noexpect(kw::Let)
2470 && let removal_span = self.prev_token.span.until(self.token.span)
2471 && let Ok(ident) = self
2472 .parse_ident_common(false)
2473 .map_err(|err| err.cancel())
2475 && self.token == TokenKind::Colon
2476 {
2477 err.span_suggestion(
2478 removal_span,
2479 "remove this `let` keyword",
2480 String::new(),
2481 Applicability::MachineApplicable,
2482 );
2483 err.note("the `let` keyword is not allowed in `struct` fields");
2484 err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
2485 err.emit();
2486 return Ok(ident);
2487 } else {
2488 self.restore_snapshot(snapshot);
2489 }
2490 err
2491 };
2492 return Err(err);
2493 }
2494 self.bump();
2495 Ok(ident)
2496 }
2497
2498 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2506 let ident = self.parse_ident()?;
2507 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)) {
2508 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)) {
2510 let params = self.parse_token_tree(); let pspan = params.span();
2512 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2513 self.unexpected()?;
2514 }
2515 let body = self.parse_token_tree(); let bspan = body.span();
2518 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]);
2520 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2521 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2522 } else {
2523 self.unexpected_any()?
2524 };
2525
2526 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2527 Ok(ItemKind::MacroDef(
2528 ident,
2529 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2530 ))
2531 }
2532
2533 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2535 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)) {
2536 let macro_rules_span = self.token.span;
2537
2538 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2539 return IsMacroRulesItem::Yes { has_bang: true };
2540 } else if self.look_ahead(1, |t| t.is_ident()) {
2541 self.dcx().emit_err(diagnostics::MacroRulesMissingBang {
2543 span: macro_rules_span,
2544 hi: macro_rules_span.shrink_to_hi(),
2545 });
2546
2547 return IsMacroRulesItem::Yes { has_bang: false };
2548 }
2549 }
2550
2551 IsMacroRulesItem::No
2552 }
2553
2554 fn parse_item_macro_rules(
2556 &mut self,
2557 vis: &Visibility,
2558 has_bang: bool,
2559 ) -> PResult<'a, ItemKind> {
2560 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 {
2563 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2565 let ident = self.parse_ident()?;
2566
2567 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2568 let span = self.prev_token.span;
2570 self.dcx().emit_err(diagnostics::MacroNameRemoveBang { span });
2571 }
2572
2573 let body = self.parse_delim_args()?;
2574 self.eat_semi_for_macro_if_needed(&body, None);
2575 self.complain_if_pub_macro(vis, true);
2576
2577 Ok(ItemKind::MacroDef(
2578 ident,
2579 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2580 ))
2581 }
2582
2583 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2586 if let VisibilityKind::Inherited = vis.kind {
2587 return;
2588 }
2589
2590 let vstr = pprust::vis_to_string(vis);
2591 let vstr = vstr.trim_end();
2592 if macro_rules {
2593 self.dcx().emit_err(diagnostics::MacroRulesVisibility { span: vis.span, vis: vstr });
2594 } else {
2595 self.dcx()
2596 .emit_err(diagnostics::MacroInvocationVisibility { span: vis.span, vis: vstr });
2597 }
2598 }
2599
2600 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
2601 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)) {
2602 self.report_invalid_macro_expansion_item(args, path);
2603 }
2604 }
2605
2606 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
2607 let span = args.dspan.entire();
2608 let mut err = self.dcx().struct_span_err(
2609 span,
2610 "macros that expand to items must be delimited with braces or followed by a semicolon",
2611 );
2612 if !span.from_expansion() {
2615 let DelimSpan { open, close } = args.dspan;
2616 if let Some(path) = path
2619 && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2620 && args.delim == Delimiter::Parenthesis
2621 {
2622 let replace =
2623 if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2624 err.multipart_suggestion(
2625 "to define a macro, remove the parentheses around the macro name",
2626 ::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())],
2627 Applicability::MachineApplicable,
2628 );
2629 } else {
2630 err.multipart_suggestion(
2631 "change the delimiters to curly braces",
2632 ::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())],
2633 Applicability::MaybeIncorrect,
2634 );
2635 err.span_suggestion(
2636 span.with_neighbor(self.token.span).shrink_to_hi(),
2637 "add a semicolon",
2638 ';',
2639 Applicability::MaybeIncorrect,
2640 );
2641 }
2642 }
2643 err.emit();
2644 }
2645
2646 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2649 if (self.token.is_keyword(kw::Enum)
2650 || self.token.is_keyword(kw::Struct)
2651 || self.token.is_keyword(kw::Union))
2652 && self.look_ahead(1, |t| t.is_ident())
2653 {
2654 let kw_token = self.token;
2655 let kw_str = pprust::token_to_string(&kw_token);
2656 let item = self.parse_item(
2657 ForceCollect::No,
2658 AllowConstBlockItems::DoesNotMatter, )?;
2660 let mut item = item.unwrap().span;
2661 if self.token == token::Comma {
2662 item = item.to(self.token.span);
2663 }
2664 self.dcx().emit_err(diagnostics::NestedAdt {
2665 span: kw_token.span,
2666 item,
2667 kw_str,
2668 keyword: keyword.as_str(),
2669 });
2670 return Ok(false);
2672 }
2673 Ok(true)
2674 }
2675}
2676
2677type ReqName = fn(Edition, IsDotDotDot) -> bool;
2686
2687#[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)]
2688pub(crate) enum IsDotDotDot {
2689 Yes,
2690 No,
2691}
2692
2693#[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)]
2701pub(crate) struct FnParseMode {
2702 pub(super) req_name: ReqName,
2728 pub(super) context: FnContext,
2731 pub(super) req_body: bool,
2750}
2751
2752#[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)]
2755pub(crate) enum FnContext {
2756 Free,
2758 Trait,
2760 Impl,
2762}
2763
2764impl<'a> Parser<'a> {
2766 fn parse_fn(
2768 &mut self,
2769 attrs: &mut AttrVec,
2770 fn_parse_mode: FnParseMode,
2771 sig_lo: Span,
2772 vis: &Visibility,
2773 case: Case,
2774 ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
2775 let fn_span = self.token.span;
2776 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)
2780 {
2781 Ok(decl) => decl,
2782 Err(old_err) => {
2783 if self.token.is_keyword(kw::For) {
2785 old_err.cancel();
2786 return Err(self.dcx().create_err(diagnostics::FnTypoWithImpl { fn_span }));
2787 } else {
2788 return Err(old_err);
2789 }
2790 }
2791 };
2792
2793 let fn_params_end = self.prev_token.span.shrink_to_hi();
2796
2797 let contract = self.parse_contract()?;
2798
2799 generics.where_clause = self.parse_where_clause()?; let fn_params_end =
2803 if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
2804
2805 let mut sig_hi = self.prev_token.span;
2806 let body =
2808 self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
2809 let fn_sig_span = sig_lo.to(sig_hi);
2810 Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
2811 }
2812
2813 fn error_fn_body_not_found(
2815 &mut self,
2816 ident_span: Span,
2817 req_body: bool,
2818 fn_params_end: Option<Span>,
2819 ) -> PResult<'a, ErrorGuaranteed> {
2820 let expected: &[_] =
2821 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)] };
2822 match self.expected_one_of_not_found(&[], expected) {
2823 Ok(error_guaranteed) => Ok(error_guaranteed),
2824 Err(mut err) => {
2825 if self.token == token::CloseBrace {
2826 err.span_label(ident_span, "while parsing this `fn`");
2829 Ok(err.emit())
2830 } else if self.token == token::RArrow
2831 && let Some(fn_params_end) = fn_params_end
2832 {
2833 let fn_trait_span =
2839 [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
2840 if self.prev_token.is_ident_named(symbol) {
2841 Some(self.prev_token.span)
2842 } else {
2843 None
2844 }
2845 });
2846
2847 let arrow_span = self.token.span;
2852 let ty_span = match self.parse_ret_ty(
2853 AllowPlus::Yes,
2854 RecoverQPath::Yes,
2855 RecoverReturnSign::Yes,
2856 ) {
2857 Ok(ty_span) => ty_span.span().shrink_to_hi(),
2858 Err(parse_error) => {
2859 parse_error.cancel();
2860 return Err(err);
2861 }
2862 };
2863 let ret_ty_span = arrow_span.to(ty_span);
2864
2865 if let Some(fn_trait_span) = fn_trait_span {
2866 err.subdiagnostic(diagnostics::FnTraitMissingParen { span: fn_trait_span });
2869 } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
2870 {
2871 err.primary_message(
2875 "return type should be specified after the function parameters",
2876 );
2877 err.subdiagnostic(diagnostics::MisplacedReturnType {
2878 fn_params_end,
2879 snippet,
2880 ret_ty_span,
2881 });
2882 }
2883 Err(err)
2884 } else {
2885 Err(err)
2886 }
2887 }
2888 }
2889 }
2890
2891 fn parse_fn_body(
2895 &mut self,
2896 attrs: &mut AttrVec,
2897 ident: &Ident,
2898 sig_hi: &mut Span,
2899 req_body: bool,
2900 fn_params_end: Option<Span>,
2901 ) -> PResult<'a, Option<Box<Block>>> {
2902 let has_semi = if req_body {
2903 self.token == TokenKind::Semi
2904 } else {
2905 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))
2907 };
2908 let (inner_attrs, body) = if has_semi {
2909 self.expect_semi()?;
2911 *sig_hi = self.prev_token.span;
2912 (AttrVec::new(), None)
2913 } 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() {
2914 let prev_in_fn_body = self.in_fn_body;
2915 self.in_fn_body = true;
2916 let res = self.parse_block_common(self.token.span, BlockCheckMode::Default, None).map(
2917 |(attrs, mut body)| {
2918 if let Some(guar) = self.fn_body_missing_semi_guar.take() {
2919 body.stmts.push(self.mk_stmt(
2920 body.span,
2921 StmtKind::Expr(self.mk_expr(body.span, ExprKind::Err(guar))),
2922 ));
2923 }
2924 (attrs, Some(body))
2925 },
2926 );
2927 self.in_fn_body = prev_in_fn_body;
2928 res?
2929 } else if self.token == token::Eq {
2930 self.bump(); let eq_sp = self.prev_token.span;
2933 let _ = self.parse_expr()?;
2934 self.expect_semi()?; let span = eq_sp.to(self.prev_token.span);
2936 let guar = self.dcx().emit_err(diagnostics::FunctionBodyEqualsExpr {
2937 span,
2938 sugg: diagnostics::FunctionBodyEqualsExprSugg {
2939 eq: eq_sp,
2940 semi: self.prev_token.span,
2941 },
2942 });
2943 (AttrVec::new(), Some(self.mk_block_err(span, guar)))
2944 } else {
2945 self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
2946 (AttrVec::new(), None)
2947 };
2948 attrs.extend(inner_attrs);
2949 Ok(body)
2950 }
2951
2952 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2953 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2954 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)) {
2957 return true;
2958 }
2959 let mut i = 0;
2960 while i < ALL_QUALS.len() {
2961 let action = self.look_ahead(i + look_ahead, |token| {
2962 if token.is_keyword(kw::Impl) {
2963 return Some(true);
2964 }
2965 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2966 return None;
2968 }
2969 Some(false)
2970 });
2971 if let Some(ret) = action {
2972 return ret;
2973 }
2974 i += 1;
2975 }
2976
2977 self.is_keyword_ahead(i, &[kw::Impl])
2978 }
2979
2980 pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
2985 const ALL_QUALS: &[ExpKeywordPair] = &[
2986 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub),
2987 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen),
2988 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const),
2989 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async),
2990 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe),
2991 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe),
2992 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern),
2993 ];
2994
2995 let quals: &[_] = if check_pub {
3000 ALL_QUALS
3001 } else {
3002 &[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)]
3003 };
3004 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))
3007 && self.look_ahead(1, |t| {
3008 t.is_keyword_case(kw::Fn, case)
3010 || (
3012 (
3013 t.is_non_raw_ident_where(|i|
3014 quals.iter().any(|exp| exp.kw == i.name)
3015 && i.is_reserved()
3017 )
3018 || case == Case::Insensitive
3019 && t.is_non_raw_ident_where(|i| quals.iter().any(|exp| {
3020 exp.kw.as_str() == i.name.as_str().to_lowercase()
3021 }))
3022 )
3023 && !self.is_unsafe_foreign_mod()
3025 && !self.is_async_gen_block()
3027 && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait, kw::Impl])
3029 )
3030 })
3031 || 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)
3033 && self.look_ahead(1, |t| t.can_begin_string_literal())
3037 && (self.tree_look_ahead(2, |tt| {
3038 match tt {
3039 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
3040 TokenTree::Delimited(..) => false,
3041 }
3042 }) == Some(true) ||
3043 (self.may_recover()
3046 && self.tree_look_ahead(2, |tt| {
3047 match tt {
3048 TokenTree::Token(t, _) =>
3049 ALL_QUALS.iter().any(|exp| {
3050 t.is_keyword(exp.kw)
3051 }),
3052 TokenTree::Delimited(..) => false,
3053 }
3054 }) == Some(true)
3055 && self.tree_look_ahead(3, |tt| {
3056 match tt {
3057 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
3058 TokenTree::Delimited(..) => false,
3059 }
3060 }) == Some(true)
3061 )
3062 )
3063 }
3064
3065 pub(super) fn parse_fn_front_matter(
3080 &mut self,
3081 orig_vis: &Visibility,
3082 case: Case,
3083 parsing_mode: FrontMatterParsingMode,
3084 ) -> PResult<'a, FnHeader> {
3085 let sp_start = self.token.span;
3086 let constness = self.parse_constness(case);
3087 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3088 && let Const::Yes(const_span) = constness
3089 {
3090 self.dcx().emit_err(FnPointerCannotBeConst {
3091 span: const_span,
3092 suggestion: const_span.until(self.token.span),
3093 });
3094 }
3095
3096 let async_start_sp = self.token.span;
3097 let coroutine_kind = self.parse_coroutine_kind(case);
3098 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
3099 && let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind
3100 {
3101 self.dcx().emit_err(FnPointerCannotBeAsync {
3102 span: async_span,
3103 suggestion: async_span.until(self.token.span),
3104 });
3105 }
3106 let unsafe_start_sp = self.token.span;
3109 let safety = self.parse_safety(case);
3110
3111 let ext_start_sp = self.token.span;
3112 let ext = self.parse_extern(case);
3113
3114 if let Some(CoroutineKind::Async { span, .. }) = coroutine_kind {
3115 if span.is_rust_2015() {
3116 self.dcx().emit_err(diagnostics::AsyncFnIn2015 {
3117 span,
3118 help: diagnostics::HelpUseLatestEdition::new(),
3119 });
3120 }
3121 }
3122
3123 match coroutine_kind {
3124 Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
3125 self.psess.gated_spans.gate(sym::gen_blocks, span);
3126 }
3127 Some(CoroutineKind::Async { .. }) | None => {}
3128 }
3129
3130 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) {
3131 match self.expect_one_of(&[], &[]) {
3135 Ok(Recovered::Yes(_)) => {}
3136 Ok(Recovered::No) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3137 Err(mut err) => {
3138 enum WrongKw {
3140 Duplicated(Span),
3141 Misplaced(Span),
3142 MisplacedDisallowedQualifier,
3147 }
3148
3149 let mut recover_constness = constness;
3151 let mut recover_coroutine_kind = coroutine_kind;
3152 let mut recover_safety = safety;
3153 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)) {
3156 match constness {
3157 Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
3158 Const::No => {
3159 recover_constness = Const::Yes(self.token.span);
3160 match parsing_mode {
3161 FrontMatterParsingMode::Function => {
3162 Some(WrongKw::Misplaced(async_start_sp))
3163 }
3164 FrontMatterParsingMode::FunctionPtrType => {
3165 self.dcx().emit_err(FnPointerCannotBeConst {
3166 span: self.token.span,
3167 suggestion: self
3168 .token
3169 .span
3170 .with_lo(self.prev_token.span.hi()),
3171 });
3172 Some(WrongKw::MisplacedDisallowedQualifier)
3173 }
3174 }
3175 }
3176 }
3177 } 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)) {
3178 match coroutine_kind {
3179 Some(CoroutineKind::Async { span, .. }) => {
3180 Some(WrongKw::Duplicated(span))
3181 }
3182 Some(CoroutineKind::AsyncGen { span, .. }) => {
3183 Some(WrongKw::Duplicated(span))
3184 }
3185 Some(CoroutineKind::Gen { .. }) => {
3186 recover_coroutine_kind = Some(CoroutineKind::AsyncGen {
3187 span: self.token.span,
3188 closure_id: DUMMY_NODE_ID,
3189 return_impl_trait_id: DUMMY_NODE_ID,
3190 });
3191 Some(WrongKw::Misplaced(unsafe_start_sp))
3193 }
3194 None => {
3195 recover_coroutine_kind = Some(CoroutineKind::Async {
3196 span: self.token.span,
3197 closure_id: DUMMY_NODE_ID,
3198 return_impl_trait_id: DUMMY_NODE_ID,
3199 });
3200 match parsing_mode {
3201 FrontMatterParsingMode::Function => {
3202 Some(WrongKw::Misplaced(async_start_sp))
3203 }
3204 FrontMatterParsingMode::FunctionPtrType => {
3205 self.dcx().emit_err(FnPointerCannotBeAsync {
3206 span: self.token.span,
3207 suggestion: self
3208 .token
3209 .span
3210 .with_lo(self.prev_token.span.hi()),
3211 });
3212 Some(WrongKw::MisplacedDisallowedQualifier)
3213 }
3214 }
3215 }
3216 }
3217 } 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)) {
3218 match safety {
3219 Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
3220 Safety::Safe(sp) => {
3221 recover_safety = Safety::Unsafe(self.token.span);
3222 Some(WrongKw::Misplaced(sp))
3223 }
3224 Safety::Default => {
3225 recover_safety = Safety::Unsafe(self.token.span);
3226 Some(WrongKw::Misplaced(ext_start_sp))
3227 }
3228 }
3229 } 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)) {
3230 match safety {
3231 Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
3232 Safety::Unsafe(sp) => {
3233 recover_safety = Safety::Safe(self.token.span);
3234 Some(WrongKw::Misplaced(sp))
3235 }
3236 Safety::Default => {
3237 recover_safety = Safety::Safe(self.token.span);
3238 Some(WrongKw::Misplaced(ext_start_sp))
3239 }
3240 }
3241 } else {
3242 None
3243 };
3244
3245 if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw {
3247 let original_kw = self
3248 .span_to_snippet(original_sp)
3249 .expect("Span extracted directly from keyword should always work");
3250
3251 err.span_suggestion(
3252 self.token_uninterpolated_span(),
3253 ::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"),
3254 "",
3255 Applicability::MachineApplicable,
3256 )
3257 .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"));
3258 }
3259 else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
3261 let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
3262 if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
3263 let misplaced_qual_sp = self.token_uninterpolated_span();
3264 let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
3265
3266 err.span_suggestion(
3267 correct_pos_sp.to(misplaced_qual_sp),
3268 ::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}`"),
3269 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", misplaced_qual,
current_qual))
})format!("{misplaced_qual} {current_qual}"),
3270 Applicability::MachineApplicable,
3271 ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
3272 }
3273 }
3274 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)) {
3276 let sp = sp_start.to(self.prev_token.span);
3277 if let Ok(snippet) = self.span_to_snippet(sp) {
3278 let current_vis = match self.parse_visibility(FollowedByType::No) {
3279 Ok(v) => v,
3280 Err(d) => {
3281 d.cancel();
3282 return Err(err);
3283 }
3284 };
3285 let vs = pprust::vis_to_string(¤t_vis);
3286 let vs = vs.trim_end();
3287
3288 if #[allow(non_exhaustive_omitted_patterns)] match orig_vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(orig_vis.kind, VisibilityKind::Inherited) {
3290 err.span_suggestion(
3291 sp_start.to(self.prev_token.span),
3292 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("visibility `{0}` must come before `{1}`",
vs, snippet))
})format!("visibility `{vs}` must come before `{snippet}`"),
3293 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", vs, snippet))
})format!("{vs} {snippet}"),
3294 Applicability::MachineApplicable,
3295 );
3296 }
3297 else {
3299 err.span_suggestion(
3300 current_vis.span,
3301 "there is already a visibility modifier, remove one",
3302 "",
3303 Applicability::MachineApplicable,
3304 )
3305 .span_note(orig_vis.span, "explicit visibility first seen here");
3306 }
3307 }
3308 }
3309
3310 if let Some(wrong_kw) = wrong_kw
3313 && self.may_recover()
3314 && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
3315 {
3316 self.bump();
3318 self.bump();
3319 if #[allow(non_exhaustive_omitted_patterns)] match wrong_kw {
WrongKw::MisplacedDisallowedQualifier => true,
_ => false,
}matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
3322 err.cancel();
3323 } else {
3324 err.emit();
3325 }
3326 return Ok(FnHeader {
3327 constness: recover_constness,
3328 safety: recover_safety,
3329 coroutine_kind: recover_coroutine_kind,
3330 ext,
3331 });
3332 }
3333
3334 return Err(err);
3335 }
3336 }
3337 }
3338
3339 Ok(FnHeader { constness, safety, coroutine_kind, ext })
3340 }
3341
3342 pub(super) fn parse_fn_decl(
3344 &mut self,
3345 fn_parse_mode: &FnParseMode,
3346 ret_allow_plus: AllowPlus,
3347 recover_return_sign: RecoverReturnSign,
3348 ) -> PResult<'a, Box<FnDecl>> {
3349 Ok(Box::new(FnDecl {
3350 inputs: self.parse_fn_params(fn_parse_mode)?,
3351 output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
3352 }))
3353 }
3354
3355 pub(super) fn parse_fn_params(
3357 &mut self,
3358 fn_parse_mode: &FnParseMode,
3359 ) -> PResult<'a, ThinVec<Param>> {
3360 let mut first_param = true;
3361 if self.token != TokenKind::OpenParen
3363 && !self.token.is_keyword(kw::For)
3365 {
3366 self.dcx().emit_err(diagnostics::MissingFnParams {
3368 span: self.prev_token.span.shrink_to_hi(),
3369 });
3370 return Ok(ThinVec::new());
3371 }
3372
3373 let (mut params, _) = self.parse_paren_comma_seq(|p| {
3374 p.recover_vcs_conflict_marker();
3375 let snapshot = p.create_snapshot_for_diagnostic();
3376 let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| {
3377 let guar = e.emit();
3378 let lo = if let TokenKind::OpenParen = p.prev_token.kind {
3382 p.prev_token.span.shrink_to_hi()
3383 } else {
3384 p.prev_token.span
3385 };
3386 p.restore_snapshot(snapshot);
3387 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)]);
3389 Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
3391 });
3392 first_param = false;
3394 param
3395 })?;
3396 self.deduplicate_recovered_params_names(&mut params);
3398 Ok(params)
3399 }
3400
3401 pub(super) fn parse_param_general(
3406 &mut self,
3407 fn_parse_mode: &FnParseMode,
3408 first_param: bool,
3409 recover_arg_parse: bool,
3410 ) -> PResult<'a, Param> {
3411 let lo = self.token.span;
3412 let attrs = self.parse_outer_attributes()?;
3413 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3414 if let Some(mut param) = this.parse_self_param()? {
3416 param.attrs = attrs;
3417 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
3418 return Ok((res?, Trailing::No, UsePreAttrPos::No));
3419 }
3420
3421 let is_dot_dot_dot = if this.token.kind == token::DotDotDot {
3422 IsDotDotDot::Yes
3423 } else {
3424 IsDotDotDot::No
3425 };
3426 let is_name_required = (fn_parse_mode.req_name)(
3427 this.token.span.with_neighbor(this.prev_token.span).edition(),
3428 is_dot_dot_dot,
3429 );
3430 let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes {
3431 this.psess.buffer_lint(
3432 VARARGS_WITHOUT_PATTERN,
3433 this.token.span,
3434 ast::CRATE_NODE_ID,
3435 diagnostics::VarargsWithoutPattern { span: this.token.span },
3436 );
3437 false
3438 } else {
3439 is_name_required
3440 };
3441 let (pat, ty) = if is_name_required || this.is_named_param() {
3442 {
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:3442",
"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(3442u32),
::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);
3443 let (pat, colon) = this.parse_fn_param_pat_colon()?;
3444 if !colon {
3445 let mut err = this.unexpected().unwrap_err();
3446 let pat_span = pat.span;
3447 return if let Some(ident) = this.parameter_without_type(
3448 &mut err,
3449 pat,
3450 is_name_required,
3451 first_param,
3452 fn_parse_mode,
3453 ) {
3454 let guar = err.emit();
3455 let mut arg = dummy_arg(ident, guar);
3456 arg.span = pat_span;
3457 Ok((arg, Trailing::No, UsePreAttrPos::No))
3458 } else {
3459 Err(err)
3460 };
3461 }
3462
3463 this.eat_incorrect_doc_comment_for_param_type();
3464 (pat, this.parse_ty_for_param()?)
3465 } else {
3466 {
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:3466",
"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(3466u32),
::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");
3467 let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
3468 this.eat_incorrect_doc_comment_for_param_type();
3469 let mut ty = this.parse_ty_for_param();
3470
3471 if let Ok(t) = &ty {
3472 if let TyKind::Path(_, Path { segments, .. }) = &t.kind
3474 && let Some(segment) = segments.last()
3475 && let Some(guar) =
3476 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)])
3477 {
3478 return Ok((
3479 dummy_arg(segment.ident, guar),
3480 Trailing::No,
3481 UsePreAttrPos::No,
3482 ));
3483 }
3484
3485 if this.token != token::Comma && this.token != token::CloseParen {
3486 ty = this.unexpected_any();
3489 }
3490 }
3491 match ty {
3492 Ok(ty) => {
3493 let pat = this.mk_pat(ty.span, PatKind::Missing);
3494 (Box::new(pat), ty)
3495 }
3496 Err(err) if this.token == token::DotDotDot => return Err(err),
3498 Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
3499 Err(err) if recover_arg_parse => {
3500 err.cancel();
3502 this.restore_snapshot(parser_snapshot_before_ty);
3503 this.recover_arg_parse()?
3504 }
3505 Err(err) => return Err(err),
3506 }
3507 };
3508
3509 let span = lo.to(this.prev_token.span);
3510
3511 Ok((
3512 Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
3513 Trailing::No,
3514 UsePreAttrPos::No,
3515 ))
3516 })
3517 }
3518
3519 fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
3521 let expect_self_ident = |this: &mut Self| match this.token.ident() {
3523 Some((ident, IdentIsRaw::No)) => {
3524 this.bump();
3525 ident
3526 }
3527 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3528 };
3529 let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime());
3531 let is_isolated_self = |this: &Self, n| {
3533 this.is_keyword_ahead(n, &[kw::SelfLower])
3534 && this.look_ahead(n + 1, |t| t != &token::PathSep)
3535 };
3536 let is_isolated_pin_const_self = |this: &Self, n| {
3538 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3539 && this.is_keyword_ahead(n + 1, &[kw::Const])
3540 && is_isolated_self(this, n + 2)
3541 };
3542 let is_isolated_mut_self =
3544 |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
3545 let is_isolated_pin_mut_self = |this: &Self, n| {
3547 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3548 && is_isolated_mut_self(this, n + 1)
3549 };
3550 let parse_self_possibly_typed = |this: &mut Self, m| {
3552 let eself_ident = expect_self_ident(this);
3553 let eself_hi = this.prev_token.span;
3554 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)) {
3555 SelfKind::Explicit(this.parse_ty()?, m)
3556 } else {
3557 SelfKind::Value(m)
3558 };
3559 Ok((eself, eself_ident, eself_hi))
3560 };
3561 let expect_self_ident_not_typed =
3562 |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
3563 let eself_ident = expect_self_ident(this);
3564
3565 if this.may_recover() && this.eat_noexpect(&token::Colon) {
3567 let snap = this.create_snapshot_for_diagnostic();
3568 match this.parse_ty() {
3569 Ok(ty) => {
3570 this.dcx().emit_err(diagnostics::IncorrectTypeOnSelf {
3571 span: ty.span,
3572 move_self_modifier: diagnostics::MoveSelfModifier {
3573 removal_span: modifier_span,
3574 insertion_span: ty.span.shrink_to_lo(),
3575 modifier: modifier.to_ref_suggestion(),
3576 },
3577 });
3578 }
3579 Err(diag) => {
3580 diag.cancel();
3581 this.restore_snapshot(snap);
3582 }
3583 }
3584 }
3585 eself_ident
3586 };
3587 let recover_self_ptr = |this: &mut Self| {
3589 this.dcx().emit_err(diagnostics::SelfArgumentPointer { span: this.token.span });
3590
3591 Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
3592 };
3593
3594 let eself_lo = self.token.span;
3598 let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
3599 token::And => {
3600 let has_lifetime = is_lifetime(self, 1);
3601 let skip_lifetime_count = has_lifetime as usize;
3602 let eself = if is_isolated_self(self, skip_lifetime_count + 1) {
3603 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3606 SelfKind::Region(lifetime, Mutability::Not)
3607 } else if is_isolated_mut_self(self, skip_lifetime_count + 1) {
3608 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3611 self.bump(); SelfKind::Region(lifetime, Mutability::Mut)
3613 } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) {
3614 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3617 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3618 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Not)
3621 } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) {
3622 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3625 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3626 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Mut)
3629 } else {
3630 return Ok(None);
3632 };
3633 let hi = self.token.span;
3634 let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
3635 (eself, self_ident, hi)
3636 }
3637 token::Star if is_isolated_self(self, 1) => {
3639 self.bump();
3640 recover_self_ptr(self)?
3641 }
3642 token::Star
3644 if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
3645 {
3646 self.bump();
3647 self.bump();
3648 recover_self_ptr(self)?
3649 }
3650 token::Ident(..) if is_isolated_self(self, 0) => {
3652 parse_self_possibly_typed(self, Mutability::Not)?
3653 }
3654 token::Ident(..) if is_isolated_mut_self(self, 0) => {
3656 self.bump();
3657 parse_self_possibly_typed(self, Mutability::Mut)?
3658 }
3659 _ => return Ok(None),
3660 };
3661
3662 let eself = respan(eself_lo.to(eself_hi), eself);
3663 Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
3664 }
3665
3666 fn is_named_param(&self) -> bool {
3667 let offset = match &self.token.kind {
3668 token::OpenInvisible(origin) => match origin {
3669 InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
3670 return self.check_noexpect_past_close_delim(&token::Colon);
3671 }
3672 _ => 0,
3673 },
3674 token::And | token::AndAnd => 1,
3675 _ if self.token.is_keyword(kw::Mut) => 1,
3676 _ => 0,
3677 };
3678
3679 self.look_ahead(offset, |t| t.is_ident())
3680 && self.look_ahead(offset + 1, |t| t == &token::Colon)
3681 }
3682
3683 fn recover_self_param(&mut self) -> bool {
3684 #[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!(
3685 self.parse_outer_attributes()
3686 .and_then(|_| self.parse_self_param())
3687 .map_err(|e| e.cancel()),
3688 Ok(Some(_))
3689 )
3690 }
3691
3692 fn try_recover_const_missing_semi(
3700 &mut self,
3701 rhs: &ConstItemRhsKind,
3702 const_span: Span,
3703 ) -> Option<Box<Expr>> {
3704 if self.token == TokenKind::Semi {
3705 return None;
3706 }
3707 let ConstItemRhsKind::Body { rhs: Some(rhs) } = rhs else {
3708 return None;
3709 };
3710 if !self.in_fn_body || !self.may_recover() || rhs.span.from_expansion() {
3711 return None;
3712 }
3713 if let Some((span, guar)) =
3714 self.missing_semi_from_binop("const", rhs, Some(const_span.shrink_to_lo()))
3715 {
3716 self.fn_body_missing_semi_guar = Some(guar);
3717 Some(self.mk_expr(span, ExprKind::Err(guar)))
3718 } else {
3719 None
3720 }
3721 }
3722}
3723
3724enum IsMacroRulesItem {
3725 Yes { has_bang: bool },
3726 No,
3727}
3728
3729#[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)]
3730pub(super) enum FrontMatterParsingMode {
3731 Function,
3733 FunctionPtrType,
3736}