1use std::fmt::Write;
2use std::mem;
3
4use ast::token::IdentIsRaw;
5use rustc_ast::ast::*;
6use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
7use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
8use rustc_ast::util::case::Case;
9use rustc_ast::{
10 attr, {self as ast},
11};
12use rustc_ast_pretty::pprust;
13use rustc_errors::codes::*;
14use rustc_errors::{Applicability, PResult, StashKey, struct_span_code_err};
15use rustc_session::lint::builtin::VARARGS_WITHOUT_PATTERN;
16use rustc_span::edit_distance::edit_distance;
17use rustc_span::edition::Edition;
18use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, source_map, sym};
19use thin_vec::{ThinVec, thin_vec};
20use tracing::debug;
21
22use super::diagnostics::{ConsumeClosingDelim, dummy_arg};
23use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
24use super::{
25 AllowConstBlockItems, AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect,
26 Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,
27};
28use crate::errors::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField};
29use crate::{exp, fluent_generated as fluent};
30
31impl<'a> Parser<'a> {
32 pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
34 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))?;
35 Ok(ast::Crate { attrs, items, spans, id: DUMMY_NODE_ID, is_placeholder: false })
36 }
37
38 fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
40 let safety = self.parse_safety(Case::Sensitive);
41 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Mod,
token_type: crate::parser::token_type::TokenType::KwMod,
}exp!(Mod))?;
42 let ident = self.parse_ident()?;
43 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)) {
44 ModKind::Unloaded
45 } else {
46 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
47 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))?;
48 attrs.extend(inner_attrs);
49 ModKind::Loaded(items, Inline::Yes, inner_span)
50 };
51 Ok(ItemKind::Mod(safety, ident, mod_kind))
52 }
53
54 pub fn parse_mod(
59 &mut self,
60 term: ExpTokenPair,
61 ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
62 let lo = self.token.span;
63 let attrs = self.parse_inner_attributes()?;
64
65 let post_attr_lo = self.token.span;
66 let mut items: ThinVec<Box<_>> = ThinVec::new();
67
68 loop {
71 while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else {
73 break;
74 };
75 items.push(item);
76 }
77
78 if !self.eat(term) {
79 let token_str = super::token_descr(&self.token);
80 if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
81 let is_let = self.token.is_keyword(kw::Let);
82 let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));
83 let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);
84
85 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected item, found {0}",
token_str))
})format!("expected item, found {token_str}");
86 let mut err = self.dcx().struct_span_err(self.token.span, msg);
87
88 let label = if is_let {
89 "`let` cannot be used for global variables"
90 } else {
91 "expected item"
92 };
93 err.span_label(self.token.span, label);
94
95 if is_let {
96 if is_let_mut {
97 err.help("consider using `static` and a `Mutex` instead of `let mut`");
98 } else if let_has_ident {
99 err.span_suggestion_short(
100 self.token.span,
101 "consider using `static` or `const` instead of `let`",
102 "static",
103 Applicability::MaybeIncorrect,
104 );
105 } else {
106 err.help("consider using `static` or `const` instead of `let`");
107 }
108 }
109 err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
110 return Err(err);
111 }
112 }
113
114 let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo());
115 let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };
116 Ok((attrs, items, mod_spans))
117 }
118}
119
120enum ReuseKind {
121 Path,
122 Impl,
123}
124
125impl<'a> Parser<'a> {
126 pub fn parse_item(
127 &mut self,
128 force_collect: ForceCollect,
129 allow_const_block_items: AllowConstBlockItems,
130 ) -> PResult<'a, Option<Box<Item>>> {
131 let fn_parse_mode =
132 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
133 self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items)
134 .map(|i| i.map(Box::new))
135 }
136
137 fn parse_item_(
138 &mut self,
139 fn_parse_mode: FnParseMode,
140 force_collect: ForceCollect,
141 const_block_items_allowed: AllowConstBlockItems,
142 ) -> PResult<'a, Option<Item>> {
143 self.recover_vcs_conflict_marker();
144 let attrs = self.parse_outer_attributes()?;
145 self.recover_vcs_conflict_marker();
146 self.parse_item_common(
147 attrs,
148 true,
149 false,
150 fn_parse_mode,
151 force_collect,
152 const_block_items_allowed,
153 )
154 }
155
156 pub(super) fn parse_item_common(
157 &mut self,
158 attrs: AttrWrapper,
159 mac_allowed: bool,
160 attrs_allowed: bool,
161 fn_parse_mode: FnParseMode,
162 force_collect: ForceCollect,
163 allow_const_block_items: AllowConstBlockItems,
164 ) -> PResult<'a, Option<Item>> {
165 if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| {
166 this.parse_item(ForceCollect::Yes, allow_const_block_items)
167 }) {
168 let mut item = item.expect("an actual item");
169 attrs.prepend_to_nt_inner(&mut item.attrs);
170 return Ok(Some(*item));
171 }
172
173 self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {
174 let lo = this.token.span;
175 let vis = this.parse_visibility(FollowedByType::No)?;
176 let mut def = this.parse_defaultness();
177 let kind = this.parse_item_kind(
178 &mut attrs,
179 mac_allowed,
180 allow_const_block_items,
181 lo,
182 &vis,
183 &mut def,
184 fn_parse_mode,
185 Case::Sensitive,
186 )?;
187 if let Some(kind) = kind {
188 this.error_on_unconsumed_default(def, &kind);
189 let span = lo.to(this.prev_token.span);
190 let id = DUMMY_NODE_ID;
191 let item = Item { attrs, id, kind, vis, span, tokens: None };
192 return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
193 }
194
195 if !#[allow(non_exhaustive_omitted_patterns)] match vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(vis.kind, VisibilityKind::Inherited) {
197 this.dcx().emit_err(errors::VisibilityNotFollowedByItem { span: vis.span, vis });
198 }
199
200 if let Defaultness::Default(span) = def {
201 this.dcx().emit_err(errors::DefaultNotFollowedByItem { span });
202 }
203
204 if !attrs_allowed {
205 this.recover_attrs_no_item(&attrs)?;
206 }
207 Ok((None, Trailing::No, UsePreAttrPos::No))
208 })
209 }
210
211 fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
213 if let Defaultness::Default(span) = def {
214 self.dcx().emit_err(errors::InappropriateDefault {
215 span,
216 article: kind.article(),
217 descr: kind.descr(),
218 });
219 }
220 }
221
222 fn parse_item_kind(
224 &mut self,
225 attrs: &mut AttrVec,
226 macros_allowed: bool,
227 allow_const_block_items: AllowConstBlockItems,
228 lo: Span,
229 vis: &Visibility,
230 def: &mut Defaultness,
231 fn_parse_mode: FnParseMode,
232 case: Case,
233 ) -> PResult<'a, Option<ItemKind>> {
234 let check_pub = def == &Defaultness::Final;
235 let mut def_ = || mem::replace(def, Defaultness::Final);
236
237 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) {
238 self.parse_use_item()?
239 } else if self.check_fn_front_matter(check_pub, case) {
240 let (ident, sig, generics, contract, body) =
242 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
243 ItemKind::Fn(Box::new(Fn {
244 defaultness: def_(),
245 ident,
246 sig,
247 generics,
248 contract,
249 body,
250 define_opaque: None,
251 eii_impls: ThinVec::new(),
252 }))
253 } 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) {
254 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) {
255 self.parse_item_extern_crate()?
257 } else {
258 self.parse_item_foreign_mod(attrs, Safety::Default)?
260 }
261 } else if self.is_unsafe_foreign_mod() {
262 let safety = self.parse_safety(Case::Sensitive);
264 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern))?;
265 self.parse_item_foreign_mod(attrs, safety)?
266 } else if let Some(safety) = self.parse_global_static_front_matter(case) {
267 let mutability = self.parse_mutability();
269 self.parse_static_item(safety, mutability)?
270 } 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() {
271 self.parse_item_trait(attrs, lo)?
273 } else if self.check_impl_frontmatter(0) {
274 self.parse_item_impl(attrs, def_(), false)?
276 } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =
277 allow_const_block_items
278 && self.check_inline_const(0)
279 {
280 if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {
282 {
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:282",
"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(282u32),
::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);
283 };
284 ItemKind::ConstBlock(self.parse_const_block_item()?)
285 } else if let Const::Yes(const_span) = self.parse_constness(case) {
286 self.recover_const_mut(const_span);
288 self.recover_missing_kw_before_item()?;
289 let (ident, generics, ty, rhs) = self.parse_const_item(attrs)?;
290 ItemKind::Const(Box::new(ConstItem {
291 defaultness: def_(),
292 ident,
293 generics,
294 ty,
295 rhs,
296 define_opaque: None,
297 }))
298 } else if let Some(kind) = self.is_reuse_item() {
299 self.parse_item_delegation(attrs, def_(), kind)?
300 } 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)
301 || 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])
302 {
303 self.parse_item_mod(attrs)?
305 } 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) {
306 self.parse_type_alias(def_())?
308 } 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) {
309 self.parse_item_enum()?
311 } 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) {
312 self.parse_item_struct()?
314 } else if self.is_kw_followed_by_ident(kw::Union) {
315 self.bump(); self.parse_item_union()?
318 } else if self.is_builtin() {
319 return self.parse_item_builtin();
321 } 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) {
322 self.parse_item_decl_macro(lo)?
324 } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {
325 self.parse_item_macro_rules(vis, has_bang)?
327 } else if self.isnt_macro_invocation()
328 && (self.token.is_ident_named(sym::import)
329 || self.token.is_ident_named(sym::using)
330 || self.token.is_ident_named(sym::include)
331 || self.token.is_ident_named(sym::require))
332 {
333 return self.recover_import_as_use();
334 } else if self.isnt_macro_invocation() && vis.kind.is_pub() {
335 self.recover_missing_kw_before_item()?;
336 return Ok(None);
337 } else if self.isnt_macro_invocation() && case == Case::Sensitive {
338 _ = def_;
339
340 return self.parse_item_kind(
342 attrs,
343 macros_allowed,
344 allow_const_block_items,
345 lo,
346 vis,
347 def,
348 fn_parse_mode,
349 Case::Insensitive,
350 );
351 } else if macros_allowed && self.check_path() {
352 if self.isnt_macro_invocation() {
353 self.recover_missing_kw_before_item()?;
354 }
355 ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
357 } else {
358 return Ok(None);
359 };
360 Ok(Some(info))
361 }
362
363 fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
364 let span = self.token.span;
365 let token_name = super::token_descr(&self.token);
366 let snapshot = self.create_snapshot_for_diagnostic();
367 self.bump();
368 match self.parse_use_item() {
369 Ok(u) => {
370 self.dcx().emit_err(errors::RecoverImportAsUse { span, token_name });
371 Ok(Some(u))
372 }
373 Err(e) => {
374 e.cancel();
375 self.restore_snapshot(snapshot);
376 Ok(None)
377 }
378 }
379 }
380
381 fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
382 let tree = self.parse_use_tree()?;
383 if let Err(mut e) = self.expect_semi() {
384 match tree.kind {
385 UseTreeKind::Glob => {
386 e.note("the wildcard token must be last on the path");
387 }
388 UseTreeKind::Nested { .. } => {
389 e.note("glob-like brace syntax must be last on the path");
390 }
391 _ => (),
392 }
393 return Err(e);
394 }
395 Ok(ItemKind::Use(tree))
396 }
397
398 pub(super) fn is_path_start_item(&mut self) -> bool {
400 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{..}) }
406
407 fn is_reuse_item(&mut self) -> Option<ReuseKind> {
408 if !self.token.is_keyword(kw::Reuse) {
409 return None;
410 }
411
412 if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {
414 Some(ReuseKind::Path)
415 } else if self.check_impl_frontmatter(1) {
416 Some(ReuseKind::Impl)
417 } else {
418 None
419 }
420 }
421
422 fn isnt_macro_invocation(&mut self) -> bool {
424 self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)
425 }
426
427 fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
430 let is_pub = self.prev_token.is_keyword(kw::Pub);
431 let is_const = self.prev_token.is_keyword(kw::Const);
432 let ident_span = self.token.span;
433 let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };
434 let insert_span = ident_span.shrink_to_lo();
435
436 let ident = if self.token.is_ident()
437 && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
438 && self.look_ahead(1, |t| {
439 #[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)
440 }) {
441 self.parse_ident_common(true).unwrap()
442 } else {
443 return Ok(());
444 };
445
446 let mut found_generics = false;
447 if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Lt,
token_type: crate::parser::token_type::TokenType::Lt,
}exp!(Lt)) {
448 found_generics = true;
449 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Gt,
token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)]);
450 self.bump(); }
452
453 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)) {
454 if self.look_ahead(1, |t| *t == token::CloseBrace) {
456 Some(errors::MissingKeywordForItemDefinition::EnumOrStruct { span })
458 } else if self.look_ahead(2, |t| *t == token::Colon)
459 || self.look_ahead(3, |t| *t == token::Colon)
460 {
461 Some(errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident })
463 } else {
464 Some(errors::MissingKeywordForItemDefinition::Enum { span, insert_span, ident })
465 }
466 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
467 self.bump(); let is_method = self.recover_self_param();
470
471 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);
472
473 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)) {
474 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)]);
475 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);
477 if is_method {
478 errors::MissingKeywordForItemDefinition::Method { span, insert_span, ident }
479 } else {
480 errors::MissingKeywordForItemDefinition::Function { span, insert_span, ident }
481 }
482 } 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)) {
483 errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }
484 } else {
485 errors::MissingKeywordForItemDefinition::Ambiguous {
486 span,
487 subdiag: if found_generics {
488 None
489 } else if let Ok(snippet) = self.span_to_snippet(ident_span) {
490 Some(errors::AmbiguousMissingKwForItemSub::SuggestMacro {
491 span: ident_span,
492 snippet,
493 })
494 } else {
495 Some(errors::AmbiguousMissingKwForItemSub::HelpMacro)
496 },
497 }
498 };
499 Some(err)
500 } else if found_generics {
501 Some(errors::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })
502 } else {
503 None
504 };
505
506 if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
507 }
508
509 fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
510 Ok(None)
512 }
513
514 fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
516 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() {
519 Ok(args) => {
521 self.eat_semi_for_macro_if_needed(&args);
522 self.complain_if_pub_macro(vis, false);
523 Ok(MacCall { path, args })
524 }
525
526 Err(mut err) => {
527 if self.token.is_ident()
529 && let [segment] = path.segments.as_slice()
530 && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
531 {
532 err.span_suggestion(
533 path.span,
534 "perhaps you meant to define a macro",
535 "macro_rules",
536 Applicability::MachineApplicable,
537 );
538 }
539 Err(err)
540 }
541 }
542 }
543
544 fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
546 let ([start @ end] | [start, .., end]) = attrs else {
547 return Ok(());
548 };
549 let msg = if end.is_doc_comment() {
550 "expected item after doc comment"
551 } else {
552 "expected item after attributes"
553 };
554 let mut err = self.dcx().struct_span_err(end.span, msg);
555 if end.is_doc_comment() {
556 err.span_label(end.span, "this doc comment doesn't document anything");
557 } else if self.token == TokenKind::Semi {
558 err.span_suggestion_verbose(
559 self.token.span,
560 "consider removing this semicolon",
561 "",
562 Applicability::MaybeIncorrect,
563 );
564 }
565 if let [.., penultimate, _] = attrs {
566 err.span_label(start.span.to(penultimate.span), "other attributes here");
567 }
568 Err(err)
569 }
570
571 fn is_async_fn(&self) -> bool {
572 self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
573 }
574
575 fn parse_polarity(&mut self) -> ast::ImplPolarity {
576 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()) {
578 self.bump(); ast::ImplPolarity::Negative(self.prev_token.span)
580 } else {
581 ast::ImplPolarity::Positive
582 }
583 }
584
585 fn parse_item_impl(
600 &mut self,
601 attrs: &mut AttrVec,
602 defaultness: Defaultness,
603 is_reuse: bool,
604 ) -> PResult<'a, ItemKind> {
605 let mut constness = self.parse_constness(Case::Sensitive);
606 let safety = self.parse_safety(Case::Sensitive);
607 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl))?;
608
609 let mut generics = if self.choose_generics_over_qpath(0) {
611 self.parse_generics()?
612 } else {
613 let mut generics = Generics::default();
614 generics.span = self.prev_token.span.shrink_to_hi();
617 generics
618 };
619
620 if let Const::No = constness {
621 constness = self.parse_constness(Case::Sensitive);
623 }
624
625 if let Const::Yes(span) = constness {
626 self.psess.gated_spans.gate(sym::const_trait_impl, span);
627 }
628
629 if (self.token_uninterpolated_span().at_least_rust_2018()
631 && self.token.is_keyword(kw::Async))
632 || self.is_kw_followed_by_ident(kw::Async)
633 {
634 self.bump();
635 self.dcx().emit_err(errors::AsyncImpl { span: self.prev_token.span });
636 }
637
638 let polarity = self.parse_polarity();
639
640 let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
642 {
643 let span = self.prev_token.span.between(self.token.span);
644 return Err(self.dcx().create_err(errors::MissingTraitInTraitImpl {
645 span,
646 for_span: span.to(self.token.span),
647 }));
648 } else {
649 self.parse_ty_with_generics_recovery(&generics)?
650 };
651
652 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));
654 let missing_for_span = self.prev_token.span.between(self.token.span);
655
656 let ty_second = if self.token == token::DotDot {
657 self.bump(); Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))
664 } else if has_for || self.token.can_begin_type() {
665 Some(self.parse_ty()?)
666 } else {
667 None
668 };
669
670 generics.where_clause = self.parse_where_clause()?;
671
672 let impl_items = if is_reuse {
673 Default::default()
674 } else {
675 self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?
676 };
677
678 let (of_trait, self_ty) = match ty_second {
679 Some(ty_second) => {
680 if !has_for {
682 self.dcx().emit_err(errors::MissingForInTraitImpl { span: missing_for_span });
683 }
684
685 let ty_first = *ty_first;
686 let path = match ty_first.kind {
687 TyKind::Path(None, path) => path,
689 other => {
690 if let TyKind::ImplTrait(_, bounds) = other
691 && let [bound] = bounds.as_slice()
692 && let GenericBound::Trait(poly_trait_ref) = bound
693 {
694 let extra_impl_kw = ty_first.span.until(bound.span());
698 self.dcx().emit_err(errors::ExtraImplKeywordInTraitImpl {
699 extra_impl_kw,
700 impl_trait_span: ty_first.span,
701 });
702 poly_trait_ref.trait_ref.path.clone()
703 } else {
704 return Err(self.dcx().create_err(
705 errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span },
706 ));
707 }
708 }
709 };
710 let trait_ref = TraitRef { path, ref_id: ty_first.id };
711
712 let of_trait =
713 Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));
714 (of_trait, ty_second)
715 }
716 None => {
717 let self_ty = ty_first;
718 let error = |modifier, modifier_name, modifier_span| {
719 self.dcx().create_err(errors::TraitImplModifierInInherentImpl {
720 span: self_ty.span,
721 modifier,
722 modifier_name,
723 modifier_span,
724 self_ty: self_ty.span,
725 })
726 };
727
728 if let Safety::Unsafe(span) = safety {
729 error("unsafe", "unsafe", span).with_code(E0197).emit();
730 }
731 if let ImplPolarity::Negative(span) = polarity {
732 error("!", "negative", span).emit();
733 }
734 if let Defaultness::Default(def_span) = defaultness {
735 error("default", "default", def_span).emit();
736 }
737 if let Const::Yes(span) = constness {
738 self.psess.gated_spans.gate(sym::const_trait_impl, span);
739 }
740 (None, self_ty)
741 }
742 };
743
744 Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))
745 }
746
747 fn parse_item_delegation(
748 &mut self,
749 attrs: &mut AttrVec,
750 defaultness: Defaultness,
751 kind: ReuseKind,
752 ) -> PResult<'a, ItemKind> {
753 let span = self.token.span;
754 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Reuse,
token_type: crate::parser::token_type::TokenType::KwReuse,
}exp!(Reuse))?;
755
756 let item_kind = match kind {
757 ReuseKind::Path => self.parse_path_like_delegation(),
758 ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),
759 }?;
760
761 self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));
762
763 Ok(item_kind)
764 }
765
766 fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {
767 Ok(if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
768 Some(self.parse_block()?)
769 } else {
770 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))?;
771 None
772 })
773 }
774
775 fn parse_impl_delegation(
776 &mut self,
777 span: Span,
778 attrs: &mut AttrVec,
779 defaultness: Defaultness,
780 ) -> PResult<'a, ItemKind> {
781 let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;
782 let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
783
784 let until_expr_span = span.to(self.prev_token.span);
785
786 let Some(of_trait) = of_trait else {
787 return Err(self
788 .dcx()
789 .create_err(errors::ImplReuseInherentImpl { span: until_expr_span }));
790 };
791
792 let body = self.parse_delegation_body()?;
793 let whole_reuse_span = span.to(self.prev_token.span);
794
795 items.push(Box::new(AssocItem {
796 id: DUMMY_NODE_ID,
797 attrs: Default::default(),
798 span: whole_reuse_span,
799 tokens: None,
800 vis: Visibility {
801 kind: VisibilityKind::Inherited,
802 span: whole_reuse_span,
803 tokens: None,
804 },
805 kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {
806 qself: None,
807 prefix: of_trait.trait_ref.path.clone(),
808 suffixes: None,
809 body,
810 })),
811 }));
812
813 Ok(impl_item)
814 }
815
816 fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {
817 let (qself, path) = if self.eat_lt() {
818 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
819 (Some(qself), path)
820 } else {
821 (None, self.parse_path(PathStyle::Expr)?)
822 };
823
824 let rename = |this: &mut Self| {
825 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 })
826 };
827
828 Ok(if self.eat_path_sep() {
829 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)) {
830 None
831 } else {
832 let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));
833 Some(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)
834 };
835
836 ItemKind::DelegationMac(Box::new(DelegationMac {
837 qself,
838 prefix: path,
839 suffixes,
840 body: self.parse_delegation_body()?,
841 }))
842 } else {
843 let rename = rename(self)?;
844 let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
845
846 ItemKind::Delegation(Box::new(Delegation {
847 id: DUMMY_NODE_ID,
848 qself,
849 path,
850 ident,
851 rename,
852 body: self.parse_delegation_body()?,
853 from_glob: false,
854 }))
855 })
856 }
857
858 fn parse_item_list<T>(
859 &mut self,
860 attrs: &mut AttrVec,
861 mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
862 ) -> PResult<'a, ThinVec<T>> {
863 let open_brace_span = self.token.span;
864
865 if self.token == TokenKind::Semi {
867 self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
868 self.bump();
869 return Ok(ThinVec::new());
870 }
871
872 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace))?;
873 attrs.extend(self.parse_inner_attributes()?);
874
875 let mut items = ThinVec::new();
876 while !self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)) {
877 if self.recover_doc_comment_before_brace() {
878 continue;
879 }
880 self.recover_vcs_conflict_marker();
881 match parse_item(self) {
882 Ok(None) => {
883 let mut is_unnecessary_semicolon = !items.is_empty()
884 && self
902 .span_to_snippet(self.prev_token.span)
903 .is_ok_and(|snippet| snippet == "}")
904 && self.token == token::Semi;
905 let mut semicolon_span = self.token.span;
906 if !is_unnecessary_semicolon {
907 is_unnecessary_semicolon =
909 self.token == token::OpenBrace && self.prev_token == token::Semi;
910 semicolon_span = self.prev_token.span;
911 }
912 let non_item_span = self.token.span;
914 let is_let = self.token.is_keyword(kw::Let);
915
916 let mut err =
917 self.dcx().struct_span_err(non_item_span, "non-item in item list");
918 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);
919 if is_let {
920 err.span_suggestion_verbose(
921 non_item_span,
922 "consider using `const` instead of `let` for associated const",
923 "const",
924 Applicability::MachineApplicable,
925 );
926 } else {
927 err.span_label(open_brace_span, "item list starts here")
928 .span_label(non_item_span, "non-item starts here")
929 .span_label(self.prev_token.span, "item list ends here");
930 }
931 if is_unnecessary_semicolon {
932 err.span_suggestion(
933 semicolon_span,
934 "consider removing this semicolon",
935 "",
936 Applicability::MaybeIncorrect,
937 );
938 }
939 err.emit();
940 break;
941 }
942 Ok(Some(item)) => items.extend(item),
943 Err(err) => {
944 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);
945 err.with_span_label(
946 open_brace_span,
947 "while parsing this item list starting here",
948 )
949 .with_span_label(self.prev_token.span, "the item list ends here")
950 .emit();
951 break;
952 }
953 }
954 }
955 Ok(items)
956 }
957
958 fn recover_doc_comment_before_brace(&mut self) -> bool {
960 if let token::DocComment(..) = self.token.kind {
961 if self.look_ahead(1, |tok| tok == &token::CloseBrace) {
962 {
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!(
964 self.dcx(),
965 self.token.span,
966 E0584,
967 "found a documentation comment that doesn't document anything",
968 )
969 .with_span_label(self.token.span, "this doc comment doesn't document anything")
970 .with_help(
971 "doc comments must come before what they document, if a comment was \
972 intended use `//`",
973 )
974 .emit();
975 self.bump();
976 return true;
977 }
978 }
979 false
980 }
981
982 fn parse_defaultness(&mut self) -> Defaultness {
984 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))
988 && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
989 {
990 self.bump(); Defaultness::Default(self.prev_token_uninterpolated_span())
992 } else {
993 Defaultness::Final
994 }
995 }
996
997 fn check_trait_front_matter(&mut self) -> bool {
999 self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Auto,
token_type: crate::parser::token_type::TokenType::KwAuto,
}exp!(Auto)) && self.is_keyword_ahead(1, &[kw::Trait])
1001 || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe)) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto])
1003 || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) && ((self.is_keyword_ahead(1, &[kw::Trait]) || self.is_keyword_ahead(1, &[kw::Auto]) && self.is_keyword_ahead(2, &[kw::Trait]))
1004 || self.is_keyword_ahead(1, &[kw::Unsafe]) && self.is_keyword_ahead(2, &[kw::Trait, kw::Auto]))
1005 }
1006
1007 fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
1009 let constness = self.parse_constness(Case::Sensitive);
1010 if let Const::Yes(span) = constness {
1011 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1012 }
1013 let safety = self.parse_safety(Case::Sensitive);
1014 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)) {
1016 self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
1017 IsAuto::Yes
1018 } else {
1019 IsAuto::No
1020 };
1021
1022 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Trait,
token_type: crate::parser::token_type::TokenType::KwTrait,
}exp!(Trait))?;
1023 let ident = self.parse_ident()?;
1024 let mut generics = self.parse_generics()?;
1025
1026 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));
1028 let span_at_colon = self.prev_token.span;
1029 let bounds = if had_colon { self.parse_generic_bounds()? } else { Vec::new() };
1030
1031 let span_before_eq = self.prev_token.span;
1032 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1033 if had_colon {
1035 let span = span_at_colon.to(span_before_eq);
1036 self.dcx().emit_err(errors::BoundsNotAllowedOnTraitAliases { span });
1037 }
1038
1039 let bounds = self.parse_generic_bounds()?;
1040 generics.where_clause = self.parse_where_clause()?;
1041 self.expect_semi()?;
1042
1043 let whole_span = lo.to(self.prev_token.span);
1044 if is_auto == IsAuto::Yes {
1045 self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span });
1046 }
1047 if let Safety::Unsafe(_) = safety {
1048 self.dcx().emit_err(errors::TraitAliasCannotBeUnsafe { span: whole_span });
1049 }
1050
1051 self.psess.gated_spans.gate(sym::trait_alias, whole_span);
1052
1053 Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
1054 } else {
1055 generics.where_clause = self.parse_where_clause()?;
1057 let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
1058 Ok(ItemKind::Trait(Box::new(Trait {
1059 constness,
1060 is_auto,
1061 safety,
1062 ident,
1063 generics,
1064 bounds,
1065 items,
1066 })))
1067 }
1068 }
1069
1070 pub fn parse_impl_item(
1071 &mut self,
1072 force_collect: ForceCollect,
1073 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1074 let fn_parse_mode =
1075 FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };
1076 self.parse_assoc_item(fn_parse_mode, force_collect)
1077 }
1078
1079 pub fn parse_trait_item(
1080 &mut self,
1081 force_collect: ForceCollect,
1082 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1083 let fn_parse_mode = FnParseMode {
1084 req_name: |edition, _| edition >= Edition::Edition2018,
1085 context: FnContext::Trait,
1086 req_body: false,
1087 };
1088 self.parse_assoc_item(fn_parse_mode, force_collect)
1089 }
1090
1091 fn parse_assoc_item(
1093 &mut self,
1094 fn_parse_mode: FnParseMode,
1095 force_collect: ForceCollect,
1096 ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
1097 Ok(self
1098 .parse_item_(
1099 fn_parse_mode,
1100 force_collect,
1101 AllowConstBlockItems::DoesNotMatter, )?
1103 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1104 let kind = match AssocItemKind::try_from(kind) {
1105 Ok(kind) => kind,
1106 Err(kind) => match kind {
1107 ItemKind::Static(box StaticItem {
1108 ident,
1109 ty,
1110 safety: _,
1111 mutability: _,
1112 expr,
1113 define_opaque,
1114 }) => {
1115 self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
1116 let rhs = expr.map(ConstItemRhs::Body);
1117 AssocItemKind::Const(Box::new(ConstItem {
1118 defaultness: Defaultness::Final,
1119 ident,
1120 generics: Generics::default(),
1121 ty,
1122 rhs,
1123 define_opaque,
1124 }))
1125 }
1126 _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
1127 },
1128 };
1129 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1130 }))
1131 }
1132
1133 fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
1139 let ident = self.parse_ident()?;
1140 let mut generics = self.parse_generics()?;
1141
1142 let bounds = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) { self.parse_generic_bounds()? } else { Vec::new() };
1144 generics.where_clause = self.parse_where_clause()?;
1145
1146 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 };
1147
1148 let after_where_clause = self.parse_where_clause()?;
1149
1150 self.expect_semi()?;
1151
1152 Ok(ItemKind::TyAlias(Box::new(TyAlias {
1153 defaultness,
1154 ident,
1155 generics,
1156 after_where_clause,
1157 bounds,
1158 ty,
1159 })))
1160 }
1161
1162 fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
1172 let lo = self.token.span;
1173
1174 let mut prefix =
1175 ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo(), tokens: None };
1176 let kind =
1177 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() {
1178 let mod_sep_ctxt = self.token.span.ctxt();
1180 if self.eat_path_sep() {
1181 prefix
1182 .segments
1183 .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
1184 }
1185
1186 self.parse_use_tree_glob_or_nested()?
1187 } else {
1188 prefix = self.parse_path(PathStyle::Mod)?;
1190
1191 if self.eat_path_sep() {
1192 self.parse_use_tree_glob_or_nested()?
1193 } else {
1194 while self.eat_noexpect(&token::Colon) {
1196 self.dcx()
1197 .emit_err(errors::SingleColonImportPath { span: self.prev_token.span });
1198
1199 self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
1201 prefix.span = lo.to(self.prev_token.span);
1202 }
1203
1204 UseTreeKind::Simple(self.parse_rename()?)
1205 }
1206 };
1207
1208 Ok(UseTree { prefix, kind, span: lo.to(self.prev_token.span) })
1209 }
1210
1211 fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
1213 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
1214 UseTreeKind::Glob
1215 } else {
1216 let lo = self.token.span;
1217 UseTreeKind::Nested {
1218 items: self.parse_use_tree_list()?,
1219 span: lo.to(self.prev_token.span),
1220 }
1221 })
1222 }
1223
1224 fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
1230 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| {
1231 p.recover_vcs_conflict_marker();
1232 Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
1233 })
1234 .map(|(r, _)| r)
1235 }
1236
1237 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1238 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)) {
1239 self.parse_ident_or_underscore().map(Some)
1240 } else {
1241 Ok(None)
1242 }
1243 }
1244
1245 fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
1246 match self.token.ident() {
1247 Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {
1248 self.bump();
1249 Ok(ident)
1250 }
1251 _ => self.parse_ident(),
1252 }
1253 }
1254
1255 fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
1264 let orig_ident = self.parse_crate_name_with_dashes()?;
1266 let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
1267 (Some(orig_ident.name), rename)
1268 } else {
1269 (None, orig_ident)
1270 };
1271 self.expect_semi()?;
1272 Ok(ItemKind::ExternCrate(orig_name, item_ident))
1273 }
1274
1275 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
1276 let ident = if self.token.is_keyword(kw::SelfLower) {
1277 self.parse_path_segment_ident()
1278 } else {
1279 self.parse_ident()
1280 }?;
1281
1282 let dash = crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Minus,
token_type: crate::parser::token_type::TokenType::Minus,
}exp!(Minus);
1283 if self.token != dash.tok {
1284 return Ok(ident);
1285 }
1286
1287 let mut dashes = ::alloc::vec::Vec::new()vec![];
1289 let mut idents = ::alloc::vec::Vec::new()vec![];
1290 while self.eat(dash) {
1291 dashes.push(self.prev_token.span);
1292 idents.push(self.parse_ident()?);
1293 }
1294
1295 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
1296 let mut fixed_name = ident.name.to_string();
1297 for part in idents {
1298 fixed_name.write_fmt(format_args!("_{0}", part.name))write!(fixed_name, "_{}", part.name).unwrap();
1299 }
1300
1301 self.dcx().emit_err(errors::ExternCrateNameWithDashes {
1302 span: fixed_name_sp,
1303 sugg: errors::ExternCrateNameWithDashesSugg { dashes },
1304 });
1305
1306 Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
1307 }
1308
1309 fn parse_item_foreign_mod(
1320 &mut self,
1321 attrs: &mut AttrVec,
1322 mut safety: Safety,
1323 ) -> PResult<'a, ItemKind> {
1324 let extern_span = self.prev_token_uninterpolated_span();
1325 let abi = self.parse_abi(); if safety == Safety::Default
1328 && self.token.is_keyword(kw::Unsafe)
1329 && self.look_ahead(1, |t| *t == token::OpenBrace)
1330 {
1331 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();
1332 safety = Safety::Unsafe(self.token.span);
1333 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));
1334 }
1335 Ok(ItemKind::ForeignMod(ast::ForeignMod {
1336 extern_span,
1337 safety,
1338 abi,
1339 items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1340 }))
1341 }
1342
1343 pub fn parse_foreign_item(
1345 &mut self,
1346 force_collect: ForceCollect,
1347 ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
1348 let fn_parse_mode = FnParseMode {
1349 req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,
1350 context: FnContext::Free,
1351 req_body: false,
1352 };
1353 Ok(self
1354 .parse_item_(
1355 fn_parse_mode,
1356 force_collect,
1357 AllowConstBlockItems::DoesNotMatter, )?
1359 .map(|Item { attrs, id, span, vis, kind, tokens }| {
1360 let kind = match ForeignItemKind::try_from(kind) {
1361 Ok(kind) => kind,
1362 Err(kind) => match kind {
1363 ItemKind::Const(box ConstItem { ident, ty, rhs, .. }) => {
1364 let const_span = Some(span.with_hi(ident.span.lo()))
1365 .filter(|span| span.can_be_used_for_suggestions());
1366 self.dcx().emit_err(errors::ExternItemCannotBeConst {
1367 ident_span: ident.span,
1368 const_span,
1369 });
1370 ForeignItemKind::Static(Box::new(StaticItem {
1371 ident,
1372 ty,
1373 mutability: Mutability::Not,
1374 expr: rhs.map(|b| match b {
1375 ConstItemRhs::TypeConst(anon_const) => anon_const.value,
1376 ConstItemRhs::Body(expr) => expr,
1377 }),
1378 safety: Safety::Default,
1379 define_opaque: None,
1380 }))
1381 }
1382 _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
1383 },
1384 };
1385 Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
1386 }))
1387 }
1388
1389 fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
1390 let span = self.psess.source_map().guess_head_span(span);
1392 let descr = kind.descr();
1393 let help = match kind {
1394 ItemKind::DelegationMac(deleg) if deleg.suffixes.is_none() => false,
1395 _ => true,
1396 };
1397 self.dcx().emit_err(errors::BadItemKind { span, descr, ctx, help });
1398 None
1399 }
1400
1401 fn is_use_closure(&self) -> bool {
1402 if self.token.is_keyword(kw::Use) {
1403 self.look_ahead(1, |token| {
1405 let dist =
1407 if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
1408
1409 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))
1410 })
1411 } else {
1412 false
1413 }
1414 }
1415
1416 fn is_unsafe_foreign_mod(&self) -> bool {
1417 if !self.token.is_keyword(kw::Unsafe) {
1419 return false;
1420 }
1421 if !self.is_keyword_ahead(1, &[kw::Extern]) {
1423 return false;
1424 }
1425
1426 let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
1428
1429 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, _)))
1434 == Some(true)
1435 }
1436
1437 fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {
1438 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) {
1439 !self.look_ahead(1, |token| {
1441 if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {
1442 return true;
1443 }
1444 #[allow(non_exhaustive_omitted_patterns)] match token.kind {
token::Or | token::OrOr => true,
_ => false,
}matches!(token.kind, token::Or | token::OrOr)
1445 })
1446 } else {
1447 (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)
1449 || 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))
1450 && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))
1451 };
1452
1453 if is_global_static {
1454 let safety = self.parse_safety(case);
1455 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);
1456 Some(safety)
1457 } else {
1458 None
1459 }
1460 }
1461
1462 fn recover_const_mut(&mut self, const_span: Span) {
1464 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)) {
1465 let span = self.prev_token.span;
1466 self.dcx()
1467 .emit_err(errors::ConstGlobalCannotBeMutable { ident_span: span, const_span });
1468 } 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)) {
1469 let span = self.prev_token.span;
1470 self.dcx().emit_err(errors::ConstLetMutuallyExclusive { span: const_span.to(span) });
1471 }
1472 }
1473
1474 fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {
1475 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1476 let const_span = self.prev_token.span;
1477 self.psess.gated_spans.gate(sym::const_block_items, const_span);
1478 let block = self.parse_block()?;
1479 Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })
1480 }
1481
1482 fn parse_static_item(
1489 &mut self,
1490 safety: Safety,
1491 mutability: Mutability,
1492 ) -> PResult<'a, ItemKind> {
1493 let ident = self.parse_ident()?;
1494
1495 if self.token == TokenKind::Lt && self.may_recover() {
1496 let generics = self.parse_generics()?;
1497 self.dcx().emit_err(errors::StaticWithGenerics { span: generics.span });
1498 }
1499
1500 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))) {
1503 (true, false) => self.parse_ty()?,
1504 (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
1507 };
1508
1509 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 };
1510
1511 self.expect_semi()?;
1512
1513 let item = StaticItem { ident, ty, safety, mutability, expr, define_opaque: None };
1514 Ok(ItemKind::Static(Box::new(item)))
1515 }
1516
1517 fn parse_const_item(
1523 &mut self,
1524 attrs: &[Attribute],
1525 ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<ast::ConstItemRhs>)> {
1526 let ident = self.parse_ident_or_underscore()?;
1527
1528 let mut generics = self.parse_generics()?;
1529
1530 if !generics.span.is_empty() {
1533 self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
1534 }
1535
1536 let ty = match (
1539 self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)),
1540 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)),
1541 ) {
1542 (true, false) => self.parse_ty()?,
1543 (colon, _) => self.recover_missing_global_item_type(colon, None),
1545 };
1546
1547 let before_where_clause =
1550 if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
1551
1552 let rhs = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1553 if attr::contains_name(attrs, sym::type_const) {
1554 Some(ConstItemRhs::TypeConst(self.parse_const_arg()?))
1555 } else {
1556 Some(ConstItemRhs::Body(self.parse_expr()?))
1557 }
1558 } else {
1559 None
1560 };
1561
1562 let after_where_clause = self.parse_where_clause()?;
1563
1564 if before_where_clause.has_where_token
1568 && let Some(rhs) = &rhs
1569 {
1570 self.dcx().emit_err(errors::WhereClauseBeforeConstBody {
1571 span: before_where_clause.span,
1572 name: ident.span,
1573 body: rhs.span(),
1574 sugg: if !after_where_clause.has_where_token {
1575 self.psess.source_map().span_to_snippet(rhs.span()).ok().map(|body_s| {
1576 errors::WhereClauseBeforeConstBodySugg {
1577 left: before_where_clause.span.shrink_to_lo(),
1578 snippet: body_s,
1579 right: before_where_clause.span.shrink_to_hi().to(rhs.span()),
1580 }
1581 })
1582 } else {
1583 None
1586 },
1587 });
1588 }
1589
1590 let mut predicates = before_where_clause.predicates;
1597 predicates.extend(after_where_clause.predicates);
1598 let where_clause = WhereClause {
1599 has_where_token: before_where_clause.has_where_token
1600 || after_where_clause.has_where_token,
1601 predicates,
1602 span: if after_where_clause.has_where_token {
1603 after_where_clause.span
1604 } else {
1605 before_where_clause.span
1606 },
1607 };
1608
1609 if where_clause.has_where_token {
1610 self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
1611 }
1612
1613 generics.where_clause = where_clause;
1614
1615 self.expect_semi()?;
1616
1617 Ok((ident, generics, ty, rhs))
1618 }
1619
1620 fn recover_missing_global_item_type(
1623 &mut self,
1624 colon_present: bool,
1625 m: Option<Mutability>,
1626 ) -> Box<Ty> {
1627 let kind = match m {
1630 Some(Mutability::Mut) => "static mut",
1631 Some(Mutability::Not) => "static",
1632 None => "const",
1633 };
1634
1635 let colon = match colon_present {
1636 true => "",
1637 false => ":",
1638 };
1639
1640 let span = self.prev_token.span.shrink_to_hi();
1641 let err = self.dcx().create_err(errors::MissingConstType { span, colon, kind });
1642 err.stash(span, StashKey::ItemNoType);
1643
1644 Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None })
1647 }
1648
1649 fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
1651 if self.token.is_keyword(kw::Struct) {
1652 let span = self.prev_token.span.to(self.token.span);
1653 let err = errors::EnumStructMutuallyExclusive { span };
1654 if self.look_ahead(1, |t| t.is_ident()) {
1655 self.bump();
1656 self.dcx().emit_err(err);
1657 } else {
1658 return Err(self.dcx().create_err(err));
1659 }
1660 }
1661
1662 let prev_span = self.prev_token.span;
1663 let ident = self.parse_ident()?;
1664 let mut generics = self.parse_generics()?;
1665 generics.where_clause = self.parse_where_clause()?;
1666
1667 let (variants, _) = if self.token == TokenKind::Semi {
1669 self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
1670 self.bump();
1671 (::thin_vec::ThinVec::new()thin_vec![], Trailing::No)
1672 } else {
1673 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| {
1674 p.parse_enum_variant(ident.span)
1675 })
1676 .map_err(|mut err| {
1677 err.span_label(ident.span, "while parsing this enum");
1678 if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {
1680 let snapshot = self.create_snapshot_for_diagnostic();
1681 self.bump();
1682 match self.parse_ty() {
1683 Ok(_) => {
1684 err.span_suggestion_verbose(
1685 prev_span,
1686 "perhaps you meant to use `struct` here",
1687 "struct",
1688 Applicability::MaybeIncorrect,
1689 );
1690 }
1691 Err(e) => {
1692 e.cancel();
1693 }
1694 }
1695 self.restore_snapshot(snapshot);
1696 }
1697 self.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1698 self.bump(); err
1700 })?
1701 };
1702
1703 let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
1704 Ok(ItemKind::Enum(ident, generics, enum_definition))
1705 }
1706
1707 fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
1708 self.recover_vcs_conflict_marker();
1709 let variant_attrs = self.parse_outer_attributes()?;
1710 self.recover_vcs_conflict_marker();
1711 let help = "enum variants can be `Variant`, `Variant = <integer>`, \
1712 `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";
1713 self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {
1714 let vlo = this.token.span;
1715
1716 let vis = this.parse_visibility(FollowedByType::No)?;
1717 if !this.recover_nested_adt_item(kw::Enum)? {
1718 return Ok((None, Trailing::No, UsePreAttrPos::No));
1719 }
1720 let ident = this.parse_field_ident("enum", vlo)?;
1721
1722 if this.token == token::Bang {
1723 if let Err(err) = this.unexpected() {
1724 err.with_note(fluent::parse_macro_expands_to_enum_variant).emit();
1725 }
1726
1727 this.bump();
1728 this.parse_delim_args()?;
1729
1730 return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));
1731 }
1732
1733 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)) {
1734 let (fields, recovered) =
1736 match this.parse_record_struct_body("struct", ident.span, false) {
1737 Ok((fields, recovered)) => (fields, recovered),
1738 Err(mut err) => {
1739 if this.token == token::Colon {
1740 return Err(err);
1742 }
1743 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace)]);
1744 this.bump(); err.span_label(span, "while parsing this enum");
1746 err.help(help);
1747 let guar = err.emit();
1748 (::thin_vec::ThinVec::new()thin_vec![], Recovered::Yes(guar))
1749 }
1750 };
1751 VariantData::Struct { fields, recovered }
1752 } else if this.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
1753 let body = match this.parse_tuple_struct_body() {
1754 Ok(body) => body,
1755 Err(mut err) => {
1756 if this.token == token::Colon {
1757 return Err(err);
1759 }
1760 this.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
1761 this.bump(); err.span_label(span, "while parsing this enum");
1763 err.help(help);
1764 err.emit();
1765 ::thin_vec::ThinVec::new()thin_vec![]
1766 }
1767 };
1768 VariantData::Tuple(body, DUMMY_NODE_ID)
1769 } else {
1770 VariantData::Unit(DUMMY_NODE_ID)
1771 };
1772
1773 let disr_expr = if this.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Eq,
token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) {
1774 Some(this.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?)
1775 } else {
1776 None
1777 };
1778
1779 let vr = ast::Variant {
1780 ident,
1781 vis,
1782 id: DUMMY_NODE_ID,
1783 attrs: variant_attrs,
1784 data: struct_def,
1785 disr_expr,
1786 span: vlo.to(this.prev_token.span),
1787 is_placeholder: false,
1788 };
1789
1790 Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))
1791 })
1792 .map_err(|mut err| {
1793 err.help(help);
1794 err
1795 })
1796 }
1797
1798 fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
1800 let ident = self.parse_ident()?;
1801
1802 let mut generics = self.parse_generics()?;
1803
1804 let vdata = if self.token.is_keyword(kw::Where) {
1819 let tuple_struct_body;
1820 (generics.where_clause, tuple_struct_body) =
1821 self.parse_struct_where_clause(ident, generics.span)?;
1822
1823 if let Some(body) = tuple_struct_body {
1824 let body = VariantData::Tuple(body, DUMMY_NODE_ID);
1826 self.expect_semi()?;
1827 body
1828 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1829 VariantData::Unit(DUMMY_NODE_ID)
1831 } else {
1832 let (fields, recovered) = self.parse_record_struct_body(
1834 "struct",
1835 ident.span,
1836 generics.where_clause.has_where_token,
1837 )?;
1838 VariantData::Struct { fields, recovered }
1839 }
1840 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
1842 VariantData::Unit(DUMMY_NODE_ID)
1843 } else if self.token == token::OpenBrace {
1845 let (fields, recovered) = self.parse_record_struct_body(
1846 "struct",
1847 ident.span,
1848 generics.where_clause.has_where_token,
1849 )?;
1850 VariantData::Struct { fields, recovered }
1851 } else if self.token == token::OpenParen {
1853 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
1854 generics.where_clause = self.parse_where_clause()?;
1855 self.expect_semi()?;
1856 body
1857 } else {
1858 let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
1859 return Err(self.dcx().create_err(err));
1860 };
1861
1862 Ok(ItemKind::Struct(ident, generics, vdata))
1863 }
1864
1865 fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
1867 let ident = self.parse_ident()?;
1868
1869 let mut generics = self.parse_generics()?;
1870
1871 let vdata = if self.token.is_keyword(kw::Where) {
1872 generics.where_clause = self.parse_where_clause()?;
1873 let (fields, recovered) = self.parse_record_struct_body(
1874 "union",
1875 ident.span,
1876 generics.where_clause.has_where_token,
1877 )?;
1878 VariantData::Struct { fields, recovered }
1879 } else if self.token == token::OpenBrace {
1880 let (fields, recovered) = self.parse_record_struct_body(
1881 "union",
1882 ident.span,
1883 generics.where_clause.has_where_token,
1884 )?;
1885 VariantData::Struct { fields, recovered }
1886 } else {
1887 let token_str = super::token_descr(&self.token);
1888 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}");
1889 let mut err = self.dcx().struct_span_err(self.token.span, msg);
1890 err.span_label(self.token.span, "expected `where` or `{` after union name");
1891 return Err(err);
1892 };
1893
1894 Ok(ItemKind::Union(ident, generics, vdata))
1895 }
1896
1897 pub(crate) fn parse_record_struct_body(
1902 &mut self,
1903 adt_ty: &str,
1904 ident_span: Span,
1905 parsed_where: bool,
1906 ) -> PResult<'a, (ThinVec<FieldDef>, Recovered)> {
1907 let mut fields = ThinVec::new();
1908 let mut recovered = Recovered::No;
1909 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
1910 while self.token != token::CloseBrace {
1911 match self.parse_field_def(adt_ty, ident_span) {
1912 Ok(field) => {
1913 fields.push(field);
1914 }
1915 Err(mut err) => {
1916 self.consume_block(
1917 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace),
1918 crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace),
1919 ConsumeClosingDelim::No,
1920 );
1921 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}"));
1922 let guar = err.emit();
1923 recovered = Recovered::Yes(guar);
1924 break;
1925 }
1926 }
1927 }
1928 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBrace,
token_type: crate::parser::token_type::TokenType::CloseBrace,
}exp!(CloseBrace))?;
1929 } else {
1930 let token_str = super::token_descr(&self.token);
1931 let where_str = if parsed_where { "" } else { "`where`, or " };
1932 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}");
1933 let mut err = self.dcx().struct_span_err(self.token.span, msg);
1934 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",));
1935 return Err(err);
1936 }
1937
1938 Ok((fields, recovered))
1939 }
1940
1941 fn parse_unsafe_field(&mut self) -> Safety {
1942 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)) {
1944 let span = self.prev_token.span;
1945 self.psess.gated_spans.gate(sym::unsafe_fields, span);
1946 Safety::Unsafe(span)
1947 } else {
1948 Safety::Default
1949 }
1950 }
1951
1952 pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
1953 self.parse_paren_comma_seq(|p| {
1956 let attrs = p.parse_outer_attributes()?;
1957 p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
1958 let mut snapshot = None;
1959 if p.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
1960 snapshot = Some(p.create_snapshot_for_diagnostic());
1964 }
1965 let lo = p.token.span;
1966 let vis = match p.parse_visibility(FollowedByType::Yes) {
1967 Ok(vis) => vis,
1968 Err(err) => {
1969 if let Some(ref mut snapshot) = snapshot {
1970 snapshot.recover_vcs_conflict_marker();
1971 }
1972 return Err(err);
1973 }
1974 };
1975 let ty = match p.parse_ty() {
1978 Ok(ty) => ty,
1979 Err(err) => {
1980 if let Some(ref mut snapshot) = snapshot {
1981 snapshot.recover_vcs_conflict_marker();
1982 }
1983 return Err(err);
1984 }
1985 };
1986 let mut default = None;
1987 if p.token == token::Eq {
1988 let mut snapshot = p.create_snapshot_for_diagnostic();
1989 snapshot.bump();
1990 match snapshot.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst) {
1991 Ok(const_expr) => {
1992 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
1993 p.psess.gated_spans.gate(sym::default_field_values, sp);
1994 p.restore_snapshot(snapshot);
1995 default = Some(const_expr);
1996 }
1997 Err(err) => {
1998 err.cancel();
1999 }
2000 }
2001 }
2002
2003 Ok((
2004 FieldDef {
2005 span: lo.to(ty.span),
2006 vis,
2007 safety: Safety::Default,
2008 ident: None,
2009 id: DUMMY_NODE_ID,
2010 ty,
2011 default,
2012 attrs,
2013 is_placeholder: false,
2014 },
2015 Trailing::from(p.token == token::Comma),
2016 UsePreAttrPos::No,
2017 ))
2018 })
2019 })
2020 .map(|(r, _)| r)
2021 }
2022
2023 fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> {
2025 self.recover_vcs_conflict_marker();
2026 let attrs = self.parse_outer_attributes()?;
2027 self.recover_vcs_conflict_marker();
2028 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2029 let lo = this.token.span;
2030 let vis = this.parse_visibility(FollowedByType::No)?;
2031 let safety = this.parse_unsafe_field();
2032 this.parse_single_struct_field(adt_ty, lo, vis, safety, attrs, ident_span)
2033 .map(|field| (field, Trailing::No, UsePreAttrPos::No))
2034 })
2035 }
2036
2037 fn parse_single_struct_field(
2039 &mut self,
2040 adt_ty: &str,
2041 lo: Span,
2042 vis: Visibility,
2043 safety: Safety,
2044 attrs: AttrVec,
2045 ident_span: Span,
2046 ) -> PResult<'a, FieldDef> {
2047 let a_var = self.parse_name_and_ty(adt_ty, lo, vis, safety, attrs)?;
2048 match self.token.kind {
2049 token::Comma => {
2050 self.bump();
2051 }
2052 token::Semi => {
2053 self.bump();
2054 let sp = self.prev_token.span;
2055 let mut err =
2056 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 `,`"));
2057 err.span_suggestion_short(
2058 sp,
2059 "replace `;` with `,`",
2060 ",",
2061 Applicability::MachineApplicable,
2062 );
2063 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}"));
2064 err.emit();
2065 }
2066 token::CloseBrace => {}
2067 token::DocComment(..) => {
2068 let previous_span = self.prev_token.span;
2069 let mut err = errors::DocCommentDoesNotDocumentAnything {
2070 span: self.token.span,
2071 missing_comma: None,
2072 };
2073 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 {
2075 self.dcx().emit_err(err);
2076 } else {
2077 let sp = previous_span.shrink_to_hi();
2078 err.missing_comma = Some(sp);
2079 return Err(self.dcx().create_err(err));
2080 }
2081 }
2082 _ => {
2083 let sp = self.prev_token.span.shrink_to_hi();
2084 let msg =
2085 ::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));
2086
2087 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
2089 && let Some(last_segment) = segments.last()
2090 {
2091 let guar = self.check_trailing_angle_brackets(
2092 last_segment,
2093 &[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)],
2094 );
2095 if let Some(_guar) = guar {
2096 let _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
2099
2100 return Ok(a_var);
2103 }
2104 }
2105
2106 let mut err = self.dcx().struct_span_err(sp, msg);
2107
2108 if self.token.is_ident()
2109 || (self.token == TokenKind::Pound
2110 && (self.look_ahead(1, |t| t == &token::OpenBracket)))
2111 {
2112 err.span_suggestion(
2115 sp,
2116 "try adding a comma",
2117 ",",
2118 Applicability::MachineApplicable,
2119 );
2120 err.emit();
2121 } else {
2122 return Err(err);
2123 }
2124 }
2125 }
2126 Ok(a_var)
2127 }
2128
2129 fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
2130 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)) {
2131 let sm = self.psess.source_map();
2132 let eq_typo = self.token == token::Eq && self.look_ahead(1, |t| t.is_path_start());
2133 let semi_typo = self.token == token::Semi
2134 && self.look_ahead(1, |t| {
2135 t.is_path_start()
2136 && match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
2139 (Ok(l), Ok(r)) => l.line == r.line,
2140 _ => true,
2141 }
2142 });
2143 if eq_typo || semi_typo {
2144 self.bump();
2145 err.with_span_suggestion_short(
2147 self.prev_token.span,
2148 "field names and their types are separated with `:`",
2149 ":",
2150 Applicability::MachineApplicable,
2151 )
2152 .emit();
2153 } else {
2154 return Err(err);
2155 }
2156 }
2157 Ok(())
2158 }
2159
2160 fn parse_name_and_ty(
2162 &mut self,
2163 adt_ty: &str,
2164 lo: Span,
2165 vis: Visibility,
2166 safety: Safety,
2167 attrs: AttrVec,
2168 ) -> PResult<'a, FieldDef> {
2169 let name = self.parse_field_ident(adt_ty, lo)?;
2170 if self.token == token::Bang {
2171 if let Err(mut err) = self.unexpected() {
2172 err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
2174 return Err(err);
2175 }
2176 }
2177 self.expect_field_ty_separator()?;
2178 let ty = self.parse_ty()?;
2179 if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
2180 self.dcx()
2181 .struct_span_err(self.token.span, "found single colon in a struct field type path")
2182 .with_span_suggestion_verbose(
2183 self.token.span,
2184 "write a path separator here",
2185 "::",
2186 Applicability::MaybeIncorrect,
2187 )
2188 .emit();
2189 }
2190 let default = if self.token == token::Eq {
2191 self.bump();
2192 let const_expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
2193 let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
2194 self.psess.gated_spans.gate(sym::default_field_values, sp);
2195 Some(const_expr)
2196 } else {
2197 None
2198 };
2199 Ok(FieldDef {
2200 span: lo.to(self.prev_token.span),
2201 ident: Some(name),
2202 vis,
2203 safety,
2204 id: DUMMY_NODE_ID,
2205 ty,
2206 default,
2207 attrs,
2208 is_placeholder: false,
2209 })
2210 }
2211
2212 fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
2215 let (ident, is_raw) = self.ident_or_err(true)?;
2216 if is_raw == IdentIsRaw::No && ident.is_reserved() {
2217 let snapshot = self.create_snapshot_for_diagnostic();
2218 let err = if self.check_fn_front_matter(false, Case::Sensitive) {
2219 let inherited_vis =
2220 Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
2221 let fn_parse_mode =
2223 FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };
2224 match self.parse_fn(
2225 &mut AttrVec::new(),
2226 fn_parse_mode,
2227 lo,
2228 &inherited_vis,
2229 Case::Insensitive,
2230 ) {
2231 Ok(_) => {
2232 self.dcx().struct_span_err(
2233 lo.to(self.prev_token.span),
2234 ::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"),
2235 )
2236 .with_help(
2237 "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
2238 )
2239 .with_help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information")
2240 }
2241 Err(err) => {
2242 err.cancel();
2243 self.restore_snapshot(snapshot);
2244 self.expected_ident_found_err()
2245 }
2246 }
2247 } 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)) {
2248 match self.parse_item_struct() {
2249 Ok(item) => {
2250 let ItemKind::Struct(ident, ..) = item else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
2251 self.dcx()
2252 .struct_span_err(
2253 lo.with_hi(ident.span.hi()),
2254 ::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"),
2255 )
2256 .with_help(
2257 "consider creating a new `struct` definition instead of nesting",
2258 )
2259 }
2260 Err(err) => {
2261 err.cancel();
2262 self.restore_snapshot(snapshot);
2263 self.expected_ident_found_err()
2264 }
2265 }
2266 } else {
2267 let mut err = self.expected_ident_found_err();
2268 if self.eat_keyword_noexpect(kw::Let)
2269 && let removal_span = self.prev_token.span.until(self.token.span)
2270 && let Ok(ident) = self
2271 .parse_ident_common(false)
2272 .map_err(|err| err.cancel())
2274 && self.token == TokenKind::Colon
2275 {
2276 err.span_suggestion(
2277 removal_span,
2278 "remove this `let` keyword",
2279 String::new(),
2280 Applicability::MachineApplicable,
2281 );
2282 err.note("the `let` keyword is not allowed in `struct` fields");
2283 err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
2284 err.emit();
2285 return Ok(ident);
2286 } else {
2287 self.restore_snapshot(snapshot);
2288 }
2289 err
2290 };
2291 return Err(err);
2292 }
2293 self.bump();
2294 Ok(ident)
2295 }
2296
2297 fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
2305 let ident = self.parse_ident()?;
2306 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)) {
2307 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)) {
2309 let params = self.parse_token_tree(); let pspan = params.span();
2311 if !self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBrace,
token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) {
2312 self.unexpected()?;
2313 }
2314 let body = self.parse_token_tree(); let bspan = body.span();
2317 let arrow = TokenTree::token_alone(token::FatArrow, pspan.between(bspan)); let tokens = TokenStream::new(<[_]>::into_vec(::alloc::boxed::box_new([params, arrow, body]))vec![params, arrow, body]);
2319 let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
2320 Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
2321 } else {
2322 self.unexpected_any()?
2323 };
2324
2325 self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
2326 Ok(ItemKind::MacroDef(
2327 ident,
2328 ast::MacroDef { body, macro_rules: false, eii_declaration: None },
2329 ))
2330 }
2331
2332 fn is_macro_rules_item(&mut self) -> IsMacroRulesItem {
2334 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)) {
2335 let macro_rules_span = self.token.span;
2336
2337 if self.look_ahead(1, |t| *t == token::Bang) && self.look_ahead(2, |t| t.is_ident()) {
2338 return IsMacroRulesItem::Yes { has_bang: true };
2339 } else if self.look_ahead(1, |t| t.is_ident()) {
2340 self.dcx().emit_err(errors::MacroRulesMissingBang {
2342 span: macro_rules_span,
2343 hi: macro_rules_span.shrink_to_hi(),
2344 });
2345
2346 return IsMacroRulesItem::Yes { has_bang: false };
2347 }
2348 }
2349
2350 IsMacroRulesItem::No
2351 }
2352
2353 fn parse_item_macro_rules(
2355 &mut self,
2356 vis: &Visibility,
2357 has_bang: bool,
2358 ) -> PResult<'a, ItemKind> {
2359 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 {
2362 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))?; }
2364 let ident = self.parse_ident()?;
2365
2366 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
2367 let span = self.prev_token.span;
2369 self.dcx().emit_err(errors::MacroNameRemoveBang { span });
2370 }
2371
2372 let body = self.parse_delim_args()?;
2373 self.eat_semi_for_macro_if_needed(&body);
2374 self.complain_if_pub_macro(vis, true);
2375
2376 Ok(ItemKind::MacroDef(
2377 ident,
2378 ast::MacroDef { body, macro_rules: true, eii_declaration: None },
2379 ))
2380 }
2381
2382 fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
2385 if let VisibilityKind::Inherited = vis.kind {
2386 return;
2387 }
2388
2389 let vstr = pprust::vis_to_string(vis);
2390 let vstr = vstr.trim_end();
2391 if macro_rules {
2392 self.dcx().emit_err(errors::MacroRulesVisibility { span: vis.span, vis: vstr });
2393 } else {
2394 self.dcx().emit_err(errors::MacroInvocationVisibility { span: vis.span, vis: vstr });
2395 }
2396 }
2397
2398 fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs) {
2399 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)) {
2400 self.report_invalid_macro_expansion_item(args);
2401 }
2402 }
2403
2404 fn report_invalid_macro_expansion_item(&self, args: &DelimArgs) {
2405 let span = args.dspan.entire();
2406 let mut err = self.dcx().struct_span_err(
2407 span,
2408 "macros that expand to items must be delimited with braces or followed by a semicolon",
2409 );
2410 if !span.from_expansion() {
2413 let DelimSpan { open, close } = args.dspan;
2414 err.multipart_suggestion(
2415 "change the delimiters to curly braces",
2416 <[_]>::into_vec(::alloc::boxed::box_new([(open, "{".to_string()),
(close, '}'.to_string())]))vec![(open, "{".to_string()), (close, '}'.to_string())],
2417 Applicability::MaybeIncorrect,
2418 );
2419 err.span_suggestion(
2420 span.with_neighbor(self.token.span).shrink_to_hi(),
2421 "add a semicolon",
2422 ';',
2423 Applicability::MaybeIncorrect,
2424 );
2425 }
2426 err.emit();
2427 }
2428
2429 fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
2432 if (self.token.is_keyword(kw::Enum)
2433 || self.token.is_keyword(kw::Struct)
2434 || self.token.is_keyword(kw::Union))
2435 && self.look_ahead(1, |t| t.is_ident())
2436 {
2437 let kw_token = self.token;
2438 let kw_str = pprust::token_to_string(&kw_token);
2439 let item = self.parse_item(
2440 ForceCollect::No,
2441 AllowConstBlockItems::DoesNotMatter, )?;
2443 let mut item = item.unwrap().span;
2444 if self.token == token::Comma {
2445 item = item.to(self.token.span);
2446 }
2447 self.dcx().emit_err(errors::NestedAdt {
2448 span: kw_token.span,
2449 item,
2450 kw_str,
2451 keyword: keyword.as_str(),
2452 });
2453 return Ok(false);
2455 }
2456 Ok(true)
2457 }
2458}
2459
2460type ReqName = fn(Edition, IsDotDotDot) -> bool;
2469
2470#[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)]
2471pub(crate) enum IsDotDotDot {
2472 Yes,
2473 No,
2474}
2475
2476#[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)]
2484pub(crate) struct FnParseMode {
2485 pub(super) req_name: ReqName,
2511 pub(super) context: FnContext,
2514 pub(super) req_body: bool,
2533}
2534
2535#[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_receiver_is_total_eq(&self) {}
}Eq)]
2538pub(crate) enum FnContext {
2539 Free,
2541 Trait,
2543 Impl,
2545}
2546
2547impl<'a> Parser<'a> {
2549 fn parse_fn(
2551 &mut self,
2552 attrs: &mut AttrVec,
2553 fn_parse_mode: FnParseMode,
2554 sig_lo: Span,
2555 vis: &Visibility,
2556 case: Case,
2557 ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
2558 let fn_span = self.token.span;
2559 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)
2563 {
2564 Ok(decl) => decl,
2565 Err(old_err) => {
2566 if self.token.is_keyword(kw::For) {
2568 old_err.cancel();
2569 return Err(self.dcx().create_err(errors::FnTypoWithImpl { fn_span }));
2570 } else {
2571 return Err(old_err);
2572 }
2573 }
2574 };
2575
2576 let fn_params_end = self.prev_token.span.shrink_to_hi();
2579
2580 let contract = self.parse_contract()?;
2581
2582 generics.where_clause = self.parse_where_clause()?; let fn_params_end =
2586 if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
2587
2588 let mut sig_hi = self.prev_token.span;
2589 let body =
2591 self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
2592 let fn_sig_span = sig_lo.to(sig_hi);
2593 Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
2594 }
2595
2596 fn error_fn_body_not_found(
2598 &mut self,
2599 ident_span: Span,
2600 req_body: bool,
2601 fn_params_end: Option<Span>,
2602 ) -> PResult<'a, ErrorGuaranteed> {
2603 let expected: &[_] =
2604 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)] };
2605 match self.expected_one_of_not_found(&[], expected) {
2606 Ok(error_guaranteed) => Ok(error_guaranteed),
2607 Err(mut err) => {
2608 if self.token == token::CloseBrace {
2609 err.span_label(ident_span, "while parsing this `fn`");
2612 Ok(err.emit())
2613 } else if self.token == token::RArrow
2614 && let Some(fn_params_end) = fn_params_end
2615 {
2616 let fn_trait_span =
2622 [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
2623 if self.prev_token.is_ident_named(symbol) {
2624 Some(self.prev_token.span)
2625 } else {
2626 None
2627 }
2628 });
2629
2630 let arrow_span = self.token.span;
2635 let ty_span = match self.parse_ret_ty(
2636 AllowPlus::Yes,
2637 RecoverQPath::Yes,
2638 RecoverReturnSign::Yes,
2639 ) {
2640 Ok(ty_span) => ty_span.span().shrink_to_hi(),
2641 Err(parse_error) => {
2642 parse_error.cancel();
2643 return Err(err);
2644 }
2645 };
2646 let ret_ty_span = arrow_span.to(ty_span);
2647
2648 if let Some(fn_trait_span) = fn_trait_span {
2649 err.subdiagnostic(errors::FnTraitMissingParen { span: fn_trait_span });
2652 } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
2653 {
2654 err.primary_message(
2658 "return type should be specified after the function parameters",
2659 );
2660 err.subdiagnostic(errors::MisplacedReturnType {
2661 fn_params_end,
2662 snippet,
2663 ret_ty_span,
2664 });
2665 }
2666 Err(err)
2667 } else {
2668 Err(err)
2669 }
2670 }
2671 }
2672 }
2673
2674 fn parse_fn_body(
2678 &mut self,
2679 attrs: &mut AttrVec,
2680 ident: &Ident,
2681 sig_hi: &mut Span,
2682 req_body: bool,
2683 fn_params_end: Option<Span>,
2684 ) -> PResult<'a, Option<Box<Block>>> {
2685 let has_semi = if req_body {
2686 self.token == TokenKind::Semi
2687 } else {
2688 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))
2690 };
2691 let (inner_attrs, body) = if has_semi {
2692 self.expect_semi()?;
2694 *sig_hi = self.prev_token.span;
2695 (AttrVec::new(), None)
2696 } 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() {
2697 self.parse_block_common(self.token.span, BlockCheckMode::Default, None)
2698 .map(|(attrs, body)| (attrs, Some(body)))?
2699 } else if self.token == token::Eq {
2700 self.bump(); let eq_sp = self.prev_token.span;
2703 let _ = self.parse_expr()?;
2704 self.expect_semi()?; let span = eq_sp.to(self.prev_token.span);
2706 let guar = self.dcx().emit_err(errors::FunctionBodyEqualsExpr {
2707 span,
2708 sugg: errors::FunctionBodyEqualsExprSugg { eq: eq_sp, semi: self.prev_token.span },
2709 });
2710 (AttrVec::new(), Some(self.mk_block_err(span, guar)))
2711 } else {
2712 self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
2713 (AttrVec::new(), None)
2714 };
2715 attrs.extend(inner_attrs);
2716 Ok(body)
2717 }
2718
2719 fn check_impl_frontmatter(&mut self, look_ahead: usize) -> bool {
2720 const ALL_QUALS: &[Symbol] = &[kw::Const, kw::Unsafe];
2721 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)) {
2724 return true;
2725 }
2726 let mut i = 0;
2727 while i < ALL_QUALS.len() {
2728 let action = self.look_ahead(i + look_ahead, |token| {
2729 if token.is_keyword(kw::Impl) {
2730 return Some(true);
2731 }
2732 if ALL_QUALS.iter().any(|&qual| token.is_keyword(qual)) {
2733 return None;
2735 }
2736 Some(false)
2737 });
2738 if let Some(ret) = action {
2739 return ret;
2740 }
2741 i += 1;
2742 }
2743
2744 self.is_keyword_ahead(i, &[kw::Impl])
2745 }
2746
2747 pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
2752 const ALL_QUALS: &[ExpKeywordPair] = &[
2753 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Pub,
token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub),
2754 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Gen,
token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen),
2755 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const),
2756 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async),
2757 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe),
2758 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Safe,
token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe),
2759 crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Extern,
token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern),
2760 ];
2761
2762 let quals: &[_] = if check_pub {
2767 ALL_QUALS
2768 } else {
2769 &[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)]
2770 };
2771 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))
2774 && self.look_ahead(1, |t| {
2775 t.is_keyword_case(kw::Fn, case)
2777 || (
2779 (
2780 t.is_non_raw_ident_where(|i|
2781 quals.iter().any(|exp| exp.kw == i.name)
2782 && i.is_reserved()
2784 )
2785 || case == Case::Insensitive
2786 && t.is_non_raw_ident_where(|i| quals.iter().any(|exp| {
2787 exp.kw.as_str() == i.name.as_str().to_lowercase()
2788 }))
2789 )
2790 && !self.is_unsafe_foreign_mod()
2792 && !self.is_async_gen_block()
2794 && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait])
2796 )
2797 })
2798 || 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)
2800 && self.look_ahead(1, |t| t.can_begin_string_literal())
2804 && (self.tree_look_ahead(2, |tt| {
2805 match tt {
2806 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
2807 TokenTree::Delimited(..) => false,
2808 }
2809 }) == Some(true) ||
2810 (self.may_recover()
2813 && self.tree_look_ahead(2, |tt| {
2814 match tt {
2815 TokenTree::Token(t, _) =>
2816 ALL_QUALS.iter().any(|exp| {
2817 t.is_keyword(exp.kw)
2818 }),
2819 TokenTree::Delimited(..) => false,
2820 }
2821 }) == Some(true)
2822 && self.tree_look_ahead(3, |tt| {
2823 match tt {
2824 TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
2825 TokenTree::Delimited(..) => false,
2826 }
2827 }) == Some(true)
2828 )
2829 )
2830 }
2831
2832 pub(super) fn parse_fn_front_matter(
2847 &mut self,
2848 orig_vis: &Visibility,
2849 case: Case,
2850 parsing_mode: FrontMatterParsingMode,
2851 ) -> PResult<'a, FnHeader> {
2852 let sp_start = self.token.span;
2853 let constness = self.parse_constness(case);
2854 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
2855 && let Const::Yes(const_span) = constness
2856 {
2857 self.dcx().emit_err(FnPointerCannotBeConst {
2858 span: const_span,
2859 suggestion: const_span.until(self.token.span),
2860 });
2861 }
2862
2863 let async_start_sp = self.token.span;
2864 let coroutine_kind = self.parse_coroutine_kind(case);
2865 if parsing_mode == FrontMatterParsingMode::FunctionPtrType
2866 && let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind
2867 {
2868 self.dcx().emit_err(FnPointerCannotBeAsync {
2869 span: async_span,
2870 suggestion: async_span.until(self.token.span),
2871 });
2872 }
2873 let unsafe_start_sp = self.token.span;
2876 let safety = self.parse_safety(case);
2877
2878 let ext_start_sp = self.token.span;
2879 let ext = self.parse_extern(case);
2880
2881 if let Some(CoroutineKind::Async { span, .. }) = coroutine_kind {
2882 if span.is_rust_2015() {
2883 self.dcx().emit_err(errors::AsyncFnIn2015 {
2884 span,
2885 help: errors::HelpUseLatestEdition::new(),
2886 });
2887 }
2888 }
2889
2890 match coroutine_kind {
2891 Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
2892 self.psess.gated_spans.gate(sym::gen_blocks, span);
2893 }
2894 Some(CoroutineKind::Async { .. }) | None => {}
2895 }
2896
2897 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) {
2898 match self.expect_one_of(&[], &[]) {
2902 Ok(Recovered::Yes(_)) => {}
2903 Ok(Recovered::No) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
2904 Err(mut err) => {
2905 enum WrongKw {
2907 Duplicated(Span),
2908 Misplaced(Span),
2909 MisplacedDisallowedQualifier,
2914 }
2915
2916 let mut recover_constness = constness;
2918 let mut recover_coroutine_kind = coroutine_kind;
2919 let mut recover_safety = safety;
2920 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)) {
2923 match constness {
2924 Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
2925 Const::No => {
2926 recover_constness = Const::Yes(self.token.span);
2927 match parsing_mode {
2928 FrontMatterParsingMode::Function => {
2929 Some(WrongKw::Misplaced(async_start_sp))
2930 }
2931 FrontMatterParsingMode::FunctionPtrType => {
2932 self.dcx().emit_err(FnPointerCannotBeConst {
2933 span: self.token.span,
2934 suggestion: self
2935 .token
2936 .span
2937 .with_lo(self.prev_token.span.hi()),
2938 });
2939 Some(WrongKw::MisplacedDisallowedQualifier)
2940 }
2941 }
2942 }
2943 }
2944 } 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)) {
2945 match coroutine_kind {
2946 Some(CoroutineKind::Async { span, .. }) => {
2947 Some(WrongKw::Duplicated(span))
2948 }
2949 Some(CoroutineKind::AsyncGen { span, .. }) => {
2950 Some(WrongKw::Duplicated(span))
2951 }
2952 Some(CoroutineKind::Gen { .. }) => {
2953 recover_coroutine_kind = Some(CoroutineKind::AsyncGen {
2954 span: self.token.span,
2955 closure_id: DUMMY_NODE_ID,
2956 return_impl_trait_id: DUMMY_NODE_ID,
2957 });
2958 Some(WrongKw::Misplaced(unsafe_start_sp))
2960 }
2961 None => {
2962 recover_coroutine_kind = Some(CoroutineKind::Async {
2963 span: self.token.span,
2964 closure_id: DUMMY_NODE_ID,
2965 return_impl_trait_id: DUMMY_NODE_ID,
2966 });
2967 match parsing_mode {
2968 FrontMatterParsingMode::Function => {
2969 Some(WrongKw::Misplaced(async_start_sp))
2970 }
2971 FrontMatterParsingMode::FunctionPtrType => {
2972 self.dcx().emit_err(FnPointerCannotBeAsync {
2973 span: self.token.span,
2974 suggestion: self
2975 .token
2976 .span
2977 .with_lo(self.prev_token.span.hi()),
2978 });
2979 Some(WrongKw::MisplacedDisallowedQualifier)
2980 }
2981 }
2982 }
2983 }
2984 } 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)) {
2985 match safety {
2986 Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
2987 Safety::Safe(sp) => {
2988 recover_safety = Safety::Unsafe(self.token.span);
2989 Some(WrongKw::Misplaced(sp))
2990 }
2991 Safety::Default => {
2992 recover_safety = Safety::Unsafe(self.token.span);
2993 Some(WrongKw::Misplaced(ext_start_sp))
2994 }
2995 }
2996 } 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)) {
2997 match safety {
2998 Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
2999 Safety::Unsafe(sp) => {
3000 recover_safety = Safety::Safe(self.token.span);
3001 Some(WrongKw::Misplaced(sp))
3002 }
3003 Safety::Default => {
3004 recover_safety = Safety::Safe(self.token.span);
3005 Some(WrongKw::Misplaced(ext_start_sp))
3006 }
3007 }
3008 } else {
3009 None
3010 };
3011
3012 if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw {
3014 let original_kw = self
3015 .span_to_snippet(original_sp)
3016 .expect("Span extracted directly from keyword should always work");
3017
3018 err.span_suggestion(
3019 self.token_uninterpolated_span(),
3020 ::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"),
3021 "",
3022 Applicability::MachineApplicable,
3023 )
3024 .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"));
3025 }
3026 else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
3028 let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
3029 if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
3030 let misplaced_qual_sp = self.token_uninterpolated_span();
3031 let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
3032
3033 err.span_suggestion(
3034 correct_pos_sp.to(misplaced_qual_sp),
3035 ::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}`"),
3036 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", misplaced_qual,
current_qual))
})format!("{misplaced_qual} {current_qual}"),
3037 Applicability::MachineApplicable,
3038 ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
3039 }
3040 }
3041 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)) {
3043 let sp = sp_start.to(self.prev_token.span);
3044 if let Ok(snippet) = self.span_to_snippet(sp) {
3045 let current_vis = match self.parse_visibility(FollowedByType::No) {
3046 Ok(v) => v,
3047 Err(d) => {
3048 d.cancel();
3049 return Err(err);
3050 }
3051 };
3052 let vs = pprust::vis_to_string(¤t_vis);
3053 let vs = vs.trim_end();
3054
3055 if #[allow(non_exhaustive_omitted_patterns)] match orig_vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(orig_vis.kind, VisibilityKind::Inherited) {
3057 err.span_suggestion(
3058 sp_start.to(self.prev_token.span),
3059 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("visibility `{0}` must come before `{1}`",
vs, snippet))
})format!("visibility `{vs}` must come before `{snippet}`"),
3060 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", vs, snippet))
})format!("{vs} {snippet}"),
3061 Applicability::MachineApplicable,
3062 );
3063 }
3064 else {
3066 err.span_suggestion(
3067 current_vis.span,
3068 "there is already a visibility modifier, remove one",
3069 "",
3070 Applicability::MachineApplicable,
3071 )
3072 .span_note(orig_vis.span, "explicit visibility first seen here");
3073 }
3074 }
3075 }
3076
3077 if let Some(wrong_kw) = wrong_kw
3080 && self.may_recover()
3081 && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
3082 {
3083 self.bump();
3085 self.bump();
3086 if #[allow(non_exhaustive_omitted_patterns)] match wrong_kw {
WrongKw::MisplacedDisallowedQualifier => true,
_ => false,
}matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
3089 err.cancel();
3090 } else {
3091 err.emit();
3092 }
3093 return Ok(FnHeader {
3094 constness: recover_constness,
3095 safety: recover_safety,
3096 coroutine_kind: recover_coroutine_kind,
3097 ext,
3098 });
3099 }
3100
3101 return Err(err);
3102 }
3103 }
3104 }
3105
3106 Ok(FnHeader { constness, safety, coroutine_kind, ext })
3107 }
3108
3109 pub(super) fn parse_fn_decl(
3111 &mut self,
3112 fn_parse_mode: &FnParseMode,
3113 ret_allow_plus: AllowPlus,
3114 recover_return_sign: RecoverReturnSign,
3115 ) -> PResult<'a, Box<FnDecl>> {
3116 Ok(Box::new(FnDecl {
3117 inputs: self.parse_fn_params(fn_parse_mode)?,
3118 output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
3119 }))
3120 }
3121
3122 pub(super) fn parse_fn_params(
3124 &mut self,
3125 fn_parse_mode: &FnParseMode,
3126 ) -> PResult<'a, ThinVec<Param>> {
3127 let mut first_param = true;
3128 if self.token != TokenKind::OpenParen
3130 && !self.token.is_keyword(kw::For)
3132 {
3133 self.dcx()
3135 .emit_err(errors::MissingFnParams { span: self.prev_token.span.shrink_to_hi() });
3136 return Ok(ThinVec::new());
3137 }
3138
3139 let (mut params, _) = self.parse_paren_comma_seq(|p| {
3140 p.recover_vcs_conflict_marker();
3141 let snapshot = p.create_snapshot_for_diagnostic();
3142 let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| {
3143 let guar = e.emit();
3144 let lo = if let TokenKind::OpenParen = p.prev_token.kind {
3148 p.prev_token.span.shrink_to_hi()
3149 } else {
3150 p.prev_token.span
3151 };
3152 p.restore_snapshot(snapshot);
3153 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)]);
3155 Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
3157 });
3158 first_param = false;
3160 param
3161 })?;
3162 self.deduplicate_recovered_params_names(&mut params);
3164 Ok(params)
3165 }
3166
3167 pub(super) fn parse_param_general(
3172 &mut self,
3173 fn_parse_mode: &FnParseMode,
3174 first_param: bool,
3175 recover_arg_parse: bool,
3176 ) -> PResult<'a, Param> {
3177 let lo = self.token.span;
3178 let attrs = self.parse_outer_attributes()?;
3179 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3180 if let Some(mut param) = this.parse_self_param()? {
3182 param.attrs = attrs;
3183 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
3184 return Ok((res?, Trailing::No, UsePreAttrPos::No));
3185 }
3186
3187 let is_dot_dot_dot = if this.token.kind == token::DotDotDot {
3188 IsDotDotDot::Yes
3189 } else {
3190 IsDotDotDot::No
3191 };
3192 let is_name_required = (fn_parse_mode.req_name)(
3193 this.token.span.with_neighbor(this.prev_token.span).edition(),
3194 is_dot_dot_dot,
3195 );
3196 let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes {
3197 this.psess.buffer_lint(
3198 VARARGS_WITHOUT_PATTERN,
3199 this.token.span,
3200 ast::CRATE_NODE_ID,
3201 errors::VarargsWithoutPattern { span: this.token.span },
3202 );
3203 false
3204 } else {
3205 is_name_required
3206 };
3207 let (pat, ty) = if is_name_required || this.is_named_param() {
3208 {
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:3208",
"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(3208u32),
::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);
3209 let (pat, colon) = this.parse_fn_param_pat_colon()?;
3210 if !colon {
3211 let mut err = this.unexpected().unwrap_err();
3212 return if let Some(ident) = this.parameter_without_type(
3213 &mut err,
3214 pat,
3215 is_name_required,
3216 first_param,
3217 fn_parse_mode,
3218 ) {
3219 let guar = err.emit();
3220 Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No))
3221 } else {
3222 Err(err)
3223 };
3224 }
3225
3226 this.eat_incorrect_doc_comment_for_param_type();
3227 (pat, this.parse_ty_for_param()?)
3228 } else {
3229 {
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:3229",
"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(3229u32),
::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");
3230 let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
3231 this.eat_incorrect_doc_comment_for_param_type();
3232 let mut ty = this.parse_ty_for_param();
3233
3234 if let Ok(t) = &ty {
3235 if let TyKind::Path(_, Path { segments, .. }) = &t.kind
3237 && let Some(segment) = segments.last()
3238 && let Some(guar) =
3239 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)])
3240 {
3241 return Ok((
3242 dummy_arg(segment.ident, guar),
3243 Trailing::No,
3244 UsePreAttrPos::No,
3245 ));
3246 }
3247
3248 if this.token != token::Comma && this.token != token::CloseParen {
3249 ty = this.unexpected_any();
3252 }
3253 }
3254 match ty {
3255 Ok(ty) => {
3256 let pat = this.mk_pat(ty.span, PatKind::Missing);
3257 (Box::new(pat), ty)
3258 }
3259 Err(err) if this.token == token::DotDotDot => return Err(err),
3261 Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
3262 Err(err) if recover_arg_parse => {
3263 err.cancel();
3265 this.restore_snapshot(parser_snapshot_before_ty);
3266 this.recover_arg_parse()?
3267 }
3268 Err(err) => return Err(err),
3269 }
3270 };
3271
3272 let span = lo.to(this.prev_token.span);
3273
3274 Ok((
3275 Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
3276 Trailing::No,
3277 UsePreAttrPos::No,
3278 ))
3279 })
3280 }
3281
3282 fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
3284 let expect_self_ident = |this: &mut Self| match this.token.ident() {
3286 Some((ident, IdentIsRaw::No)) => {
3287 this.bump();
3288 ident
3289 }
3290 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
3291 };
3292 let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime());
3294 let is_isolated_self = |this: &Self, n| {
3296 this.is_keyword_ahead(n, &[kw::SelfLower])
3297 && this.look_ahead(n + 1, |t| t != &token::PathSep)
3298 };
3299 let is_isolated_pin_const_self = |this: &Self, n| {
3301 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3302 && this.is_keyword_ahead(n + 1, &[kw::Const])
3303 && is_isolated_self(this, n + 2)
3304 };
3305 let is_isolated_mut_self =
3307 |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
3308 let is_isolated_pin_mut_self = |this: &Self, n| {
3310 this.look_ahead(n, |token| token.is_ident_named(sym::pin))
3311 && is_isolated_mut_self(this, n + 1)
3312 };
3313 let parse_self_possibly_typed = |this: &mut Self, m| {
3315 let eself_ident = expect_self_ident(this);
3316 let eself_hi = this.prev_token.span;
3317 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)) {
3318 SelfKind::Explicit(this.parse_ty()?, m)
3319 } else {
3320 SelfKind::Value(m)
3321 };
3322 Ok((eself, eself_ident, eself_hi))
3323 };
3324 let expect_self_ident_not_typed =
3325 |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
3326 let eself_ident = expect_self_ident(this);
3327
3328 if this.may_recover() && this.eat_noexpect(&token::Colon) {
3330 let snap = this.create_snapshot_for_diagnostic();
3331 match this.parse_ty() {
3332 Ok(ty) => {
3333 this.dcx().emit_err(errors::IncorrectTypeOnSelf {
3334 span: ty.span,
3335 move_self_modifier: errors::MoveSelfModifier {
3336 removal_span: modifier_span,
3337 insertion_span: ty.span.shrink_to_lo(),
3338 modifier: modifier.to_ref_suggestion(),
3339 },
3340 });
3341 }
3342 Err(diag) => {
3343 diag.cancel();
3344 this.restore_snapshot(snap);
3345 }
3346 }
3347 }
3348 eself_ident
3349 };
3350 let recover_self_ptr = |this: &mut Self| {
3352 this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
3353
3354 Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
3355 };
3356
3357 let eself_lo = self.token.span;
3361 let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
3362 token::And => {
3363 let has_lifetime = is_lifetime(self, 1);
3364 let skip_lifetime_count = has_lifetime as usize;
3365 let eself = if is_isolated_self(self, skip_lifetime_count + 1) {
3366 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3369 SelfKind::Region(lifetime, Mutability::Not)
3370 } else if is_isolated_mut_self(self, skip_lifetime_count + 1) {
3371 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3374 self.bump(); SelfKind::Region(lifetime, Mutability::Mut)
3376 } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) {
3377 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3380 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3381 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Not)
3384 } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) {
3385 self.bump(); let lifetime = has_lifetime.then(|| self.expect_lifetime());
3388 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
3389 self.bump(); self.bump(); SelfKind::Pinned(lifetime, Mutability::Mut)
3392 } else {
3393 return Ok(None);
3395 };
3396 let hi = self.token.span;
3397 let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
3398 (eself, self_ident, hi)
3399 }
3400 token::Star if is_isolated_self(self, 1) => {
3402 self.bump();
3403 recover_self_ptr(self)?
3404 }
3405 token::Star
3407 if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
3408 {
3409 self.bump();
3410 self.bump();
3411 recover_self_ptr(self)?
3412 }
3413 token::Ident(..) if is_isolated_self(self, 0) => {
3415 parse_self_possibly_typed(self, Mutability::Not)?
3416 }
3417 token::Ident(..) if is_isolated_mut_self(self, 0) => {
3419 self.bump();
3420 parse_self_possibly_typed(self, Mutability::Mut)?
3421 }
3422 _ => return Ok(None),
3423 };
3424
3425 let eself = source_map::respan(eself_lo.to(eself_hi), eself);
3426 Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
3427 }
3428
3429 fn is_named_param(&self) -> bool {
3430 let offset = match &self.token.kind {
3431 token::OpenInvisible(origin) => match origin {
3432 InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
3433 return self.check_noexpect_past_close_delim(&token::Colon);
3434 }
3435 _ => 0,
3436 },
3437 token::And | token::AndAnd => 1,
3438 _ if self.token.is_keyword(kw::Mut) => 1,
3439 _ => 0,
3440 };
3441
3442 self.look_ahead(offset, |t| t.is_ident())
3443 && self.look_ahead(offset + 1, |t| t == &token::Colon)
3444 }
3445
3446 fn recover_self_param(&mut self) -> bool {
3447 #[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!(
3448 self.parse_outer_attributes()
3449 .and_then(|_| self.parse_self_param())
3450 .map_err(|e| e.cancel()),
3451 Ok(Some(_))
3452 )
3453 }
3454}
3455
3456enum IsMacroRulesItem {
3457 Yes { has_bang: bool },
3458 No,
3459}
3460
3461#[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_receiver_is_total_eq(&self) {}
}Eq)]
3462pub(super) enum FrontMatterParsingMode {
3463 Function,
3465 FunctionPtrType,
3468}