compiler/rustc_parse/src/parser/item.rs RUST 3,701 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 3,701.
1use std::fmt::Write;2use std::mem;34use ast::token::IdentIsRaw;5use rustc_ast as ast;6use rustc_ast::ast::*;7use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};8use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};9use rustc_ast::util::case::Case;10use rustc_ast_pretty::pprust;11use rustc_errors::codes::*;12use rustc_errors::{Applicability, PResult, StashKey, msg, struct_span_code_err};13use rustc_session::lint::builtin::VARARGS_WITHOUT_PATTERN;14use rustc_span::edit_distance::edit_distance;15use rustc_span::edition::Edition;16use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, respan, sym};17use thin_vec::{ThinVec, thin_vec};18use tracing::debug;1920use super::diagnostics::{ConsumeClosingDelim, dummy_arg};21use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};22use super::{23    AllowConstBlockItems, AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect,24    Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,25};26use crate::errors::{27    self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField,28    UseDoubleColonSuggestion, UseRegularStructSuggestion,29};30use crate::exp;3132impl<'a> Parser<'a> {33    /// Parses a source module as a crate. This is the main entry point for the parser.34    pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {35        let (attrs, items, spans) = self.parse_mod(exp!(Eof))?;36        Ok(ast::Crate { attrs, items, spans, id: DUMMY_NODE_ID, is_placeholder: false })37    }3839    /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.40    fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {41        let safety = self.parse_safety(Case::Sensitive);42        self.expect_keyword(exp!(Mod))?;43        let ident = self.parse_ident()?;44        let mod_kind = if self.eat(exp!(Semi)) {45            ModKind::Unloaded46        } else {47            self.expect(exp!(OpenBrace))?;48            let (inner_attrs, items, inner_span) = self.parse_mod(exp!(CloseBrace))?;49            attrs.extend(inner_attrs);50            ModKind::Loaded(items, Inline::Yes, inner_span)51        };52        Ok(ItemKind::Mod(safety, ident, mod_kind))53    }5455    /// Parses the contents of a module (inner attributes followed by module items).56    /// We exit once we hit `term` which can be either57    /// - EOF (for files)58    /// - `}` for mod items59    pub fn parse_mod(60        &mut self,61        term: ExpTokenPair,62    ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {63        let lo = self.token.span;64        let attrs = self.parse_inner_attributes()?;6566        let post_attr_lo = self.token.span;67        let mut items: ThinVec<Box<_>> = ThinVec::new();6869        // There shouldn't be any stray semicolons before or after items.70        // `parse_item` consumes the appropriate semicolons so any leftover is an error.71        loop {72            while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} // Eat all bad semicolons73            let Some(item) = self.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)? else {74                break;75            };76            items.push(item);77        }7879        if !self.eat(term) {80            let token_str = super::token_descr(&self.token);81            if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {82                let is_let = self.token.is_keyword(kw::Let);83                let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut));84                let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let);8586                let msg = format!("expected item, found {token_str}");87                let mut err = self.dcx().struct_span_err(self.token.span, msg);8889                let label = if is_let {90                    "`let` cannot be used for global variables"91                } else {92                    "expected item"93                };94                err.span_label(self.token.span, label);9596                if is_let {97                    if is_let_mut {98                        err.help("consider using `static` and a `Mutex` instead of `let mut`");99                    } else if let_has_ident {100                        err.span_suggestion_short(101                            self.token.span,102                            "consider using `static` or `const` instead of `let`",103                            "static",104                            Applicability::MaybeIncorrect,105                        );106                    } else {107                        err.help("consider using `static` or `const` instead of `let`");108                    }109                }110                err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");111                return Err(err);112            }113        }114115        let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo());116        let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };117        Ok((attrs, items, mod_spans))118    }119}120121enum ReuseKind {122    Path,123    Impl,124}125126impl<'a> Parser<'a> {127    pub fn parse_item(128        &mut self,129        force_collect: ForceCollect,130        allow_const_block_items: AllowConstBlockItems,131    ) -> PResult<'a, Option<Box<Item>>> {132        let fn_parse_mode =133            FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true };134        self.parse_item_(fn_parse_mode, force_collect, allow_const_block_items)135            .map(|i| i.map(Box::new))136    }137138    fn parse_item_(139        &mut self,140        fn_parse_mode: FnParseMode,141        force_collect: ForceCollect,142        const_block_items_allowed: AllowConstBlockItems,143    ) -> PResult<'a, Option<Item>> {144        self.recover_vcs_conflict_marker();145        let attrs = self.parse_outer_attributes()?;146        self.recover_vcs_conflict_marker();147        self.parse_item_common(148            attrs,149            true,150            false,151            fn_parse_mode,152            force_collect,153            const_block_items_allowed,154        )155    }156157    pub(super) fn parse_item_common(158        &mut self,159        attrs: AttrWrapper,160        mac_allowed: bool,161        attrs_allowed: bool,162        fn_parse_mode: FnParseMode,163        force_collect: ForceCollect,164        allow_const_block_items: AllowConstBlockItems,165    ) -> PResult<'a, Option<Item>> {166        if let Some(item) = self.eat_metavar_seq(MetaVarKind::Item, |this| {167            this.parse_item(ForceCollect::Yes, allow_const_block_items)168        }) {169            let mut item = item.expect("an actual item");170            attrs.prepend_to_nt_inner(&mut item.attrs);171            return Ok(Some(*item));172        }173174        self.collect_tokens(None, attrs, force_collect, |this, mut attrs| {175            let lo = this.token.span;176            let vis = this.parse_visibility(FollowedByType::No)?;177            let mut def = this.parse_defaultness();178            let kind = this.parse_item_kind(179                &mut attrs,180                mac_allowed,181                allow_const_block_items,182                lo,183                &vis,184                &mut def,185                fn_parse_mode,186                Case::Sensitive,187            )?;188            if let Some(kind) = kind {189                this.error_on_unconsumed_default(def, &kind);190                let span = lo.to(this.prev_token.span);191                let id = DUMMY_NODE_ID;192                let item = Item { attrs, id, kind, vis, span, tokens: None };193                return Ok((Some(item), Trailing::No, UsePreAttrPos::No));194            }195196            // At this point, we have failed to parse an item.197            if !matches!(vis.kind, VisibilityKind::Inherited) {198                let vis_str = pprust::vis_to_string(&vis).trim_end().to_string();199                let mut err = this.dcx().create_err(errors::VisibilityNotFollowedByItem {200                    span: vis.span,201                    vis: vis_str,202                });203                if let Some((ident, _)) = this.token.ident()204                    && !ident.is_used_keyword()205                    && let Some((similar_kw, is_incorrect_case)) = ident206                        .name207                        .find_similar(&rustc_span::symbol::used_keywords(|| ident.span.edition()))208                {209                    err.subdiagnostic(errors::MisspelledKw {210                        similar_kw: similar_kw.to_string(),211                        span: ident.span,212                        is_incorrect_case,213                    });214                }215                err.emit();216            }217218            if let Defaultness::Default(span) = def {219                this.dcx().emit_err(errors::DefaultNotFollowedByItem { span });220            } else if let Defaultness::Final(span) = def {221                this.dcx().emit_err(errors::FinalNotFollowedByItem { span });222            }223224            if !attrs_allowed {225                this.recover_attrs_no_item(&attrs)?;226            }227            Ok((None, Trailing::No, UsePreAttrPos::No))228        })229    }230231    /// Error in-case `default`/`final` was parsed in an in-appropriate context.232    fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {233        match def {234            Defaultness::Default(span) => {235                self.dcx().emit_err(errors::InappropriateDefault {236                    span,237                    article: kind.article(),238                    descr: kind.descr(),239                });240            }241            Defaultness::Final(span) => {242                self.dcx().emit_err(errors::InappropriateFinal {243                    span,244                    article: kind.article(),245                    descr: kind.descr(),246                });247            }248            Defaultness::Implicit => (),249        }250    }251252    /// Parses one of the items allowed by the flags.253    fn parse_item_kind(254        &mut self,255        attrs: &mut AttrVec,256        macros_allowed: bool,257        allow_const_block_items: AllowConstBlockItems,258        lo: Span,259        vis: &Visibility,260        def: &mut Defaultness,261        fn_parse_mode: FnParseMode,262        case: Case,263    ) -> PResult<'a, Option<ItemKind>> {264        let check_pub = def == &Defaultness::Implicit;265        let mut def_ = || mem::replace(def, Defaultness::Implicit);266267        let info = if !self.is_use_closure() && self.eat_keyword_case(exp!(Use), case) {268            self.parse_use_item()?269        } else if self.check_fn_front_matter(check_pub, case) {270            // FUNCTION ITEM271            let defaultness = def_();272            if let Defaultness::Default(span) = defaultness {273                // Default functions should only require feature `min_specialization`. We remove the274                // `specialization` tag again as such spans *require* feature `specialization` to be275                // enabled. In a later stage, we make `specialization` imply `min_specialization`.276                self.psess.gated_spans.gate(sym::min_specialization, span);277                self.psess.gated_spans.ungate_last(sym::specialization, span);278            }279            let (ident, sig, generics, contract, body) =280                self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;281            ItemKind::Fn(Box::new(Fn {282                defaultness,283                ident,284                sig,285                generics,286                contract,287                body,288                define_opaque: None,289                eii_impls: ThinVec::new(),290            }))291        } else if self.eat_keyword_case(exp!(Extern), case) {292            if self.eat_keyword_case(exp!(Crate), case) {293                // EXTERN CRATE294                self.parse_item_extern_crate()?295            } else {296                // EXTERN BLOCK297                self.parse_item_foreign_mod(attrs, Safety::Default)?298            }299        } else if self.is_unsafe_foreign_mod() {300            // EXTERN BLOCK301            let safety = self.parse_safety(Case::Sensitive);302            self.expect_keyword(exp!(Extern))?;303            self.parse_item_foreign_mod(attrs, safety)?304        } else if let Some(safety) = self.parse_global_static_front_matter(case) {305            // STATIC ITEM306            let mutability = self.parse_mutability();307            self.parse_static_item(safety, mutability)?308        } else if self.check_keyword_case(exp!(Trait), case) || self.check_trait_front_matter() {309            // TRAIT ITEM310            self.parse_item_trait(attrs, lo)?311        } else if self.check_impl_frontmatter(0) {312            // IMPL ITEM313            self.parse_item_impl(attrs, def_(), false)?314        } else if let AllowConstBlockItems::Yes | AllowConstBlockItems::DoesNotMatter =315            allow_const_block_items316            && self.check_inline_const(0)317        {318            // CONST BLOCK ITEM319            if let AllowConstBlockItems::DoesNotMatter = allow_const_block_items {320                debug!("Parsing a const block item that does not matter: {:?}", self.token.span);321            };322            ItemKind::ConstBlock(self.parse_const_block_item()?)323        } else if let Const::Yes(const_span) = self.parse_constness(case) {324            // CONST ITEM325            self.recover_const_mut(const_span);326            self.recover_missing_kw_before_item()?;327            let (ident, generics, ty, rhs_kind) = self.parse_const_item(false, const_span)?;328            ItemKind::Const(Box::new(ConstItem {329                defaultness: def_(),330                ident,331                generics,332                ty,333                rhs_kind,334                define_opaque: None,335            }))336        } else if let Some(kind) = self.is_reuse_item() {337            self.parse_item_delegation(attrs, def_(), kind)?338        } else if self.check_keyword_case(exp!(Mod), case)339            || self.check_keyword_case(exp!(Unsafe), case) && self.is_keyword_ahead(1, &[kw::Mod])340        {341            // MODULE ITEM342            self.parse_item_mod(attrs)?343        } else if self.eat_keyword_case(exp!(Type), case) {344            if let Const::Yes(const_span) = self.parse_constness(case) {345                // TYPE CONST (mgca)346                self.recover_const_mut(const_span);347                self.recover_missing_kw_before_item()?;348                let (ident, generics, ty, rhs_kind) = self.parse_const_item(true, const_span)?;349                // Make sure this is only allowed if the feature gate is enabled.350                // #![feature(mgca_type_const_syntax)]351                self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span));352                ItemKind::Const(Box::new(ConstItem {353                    defaultness: def_(),354                    ident,355                    generics,356                    ty,357                    rhs_kind,358                    define_opaque: None,359                }))360            } else {361                // TYPE ITEM362                self.parse_type_alias(def_())?363            }364        } else if self.eat_keyword_case(exp!(Enum), case) {365            // ENUM ITEM366            self.parse_item_enum()?367        } else if self.eat_keyword_case(exp!(Struct), case) {368            // STRUCT ITEM369            self.parse_item_struct()?370        } else if self.is_kw_followed_by_ident(kw::Union) {371            // UNION ITEM372            self.bump(); // `union`373            self.parse_item_union()?374        } else if self.is_builtin() {375            // BUILTIN# ITEM376            return self.parse_item_builtin();377        } else if self.eat_keyword_case(exp!(Macro), case) {378            // MACROS 2.0 ITEM379            self.parse_item_decl_macro(lo)?380        } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() {381            // MACRO_RULES ITEM382            self.parse_item_macro_rules(vis, has_bang)?383        } else if self.isnt_macro_invocation()384            && (self.token.is_ident_named(sym::import)385                || self.token.is_ident_named(sym::using)386                || self.token.is_ident_named(sym::include)387                || self.token.is_ident_named(sym::require))388        {389            return self.recover_import_as_use();390        } else if self.isnt_macro_invocation() && vis.kind.is_pub() {391            self.recover_missing_kw_before_item()?;392            return Ok(None);393        } else if self.isnt_macro_invocation() && case == Case::Sensitive {394            _ = def_;395396            // Recover wrong cased keywords397            return self.parse_item_kind(398                attrs,399                macros_allowed,400                allow_const_block_items,401                lo,402                vis,403                def,404                fn_parse_mode,405                Case::Insensitive,406            );407        } else if macros_allowed && self.check_path() {408            if self.isnt_macro_invocation() {409                self.recover_missing_kw_before_item()?;410            }411            // MACRO INVOCATION ITEM412            ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))413        } else {414            return Ok(None);415        };416        Ok(Some(info))417    }418419    fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {420        let span = self.token.span;421        let token_name = super::token_descr(&self.token);422        let snapshot = self.create_snapshot_for_diagnostic();423        self.bump();424        match self.parse_use_item() {425            Ok(u) => {426                self.dcx().emit_err(errors::RecoverImportAsUse { span, token_name });427                Ok(Some(u))428            }429            Err(e) => {430                e.cancel();431                self.restore_snapshot(snapshot);432                Ok(None)433            }434        }435    }436437    fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {438        let tree = self.parse_use_tree()?;439        if let Err(mut e) = self.expect_semi() {440            match tree.kind {441                UseTreeKind::Glob(_) => {442                    e.note("the wildcard token must be last on the path");443                }444                UseTreeKind::Nested { .. } => {445                    e.note("glob-like brace syntax must be last on the path");446                }447                _ => (),448            }449            return Err(e);450        }451        Ok(ItemKind::Use(tree))452    }453454    /// When parsing a statement, would the start of a path be an item?455    pub(super) fn is_path_start_item(&mut self) -> bool {456        self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }`457        || self.is_reuse_item().is_some() // yes: `reuse impl Trait for Struct { self.0 }`, yes: `reuse some_path::foo;`458        || self.check_trait_front_matter() // no: `auto::b`, yes: `auto trait X { .. }`459        || self.is_async_fn() // no(2015): `async::b`, yes: `async fn`460        || matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) // no: `macro_rules::b`, yes: `macro_rules! mac`461    }462463    fn is_reuse_item(&mut self) -> Option<ReuseKind> {464        if !self.token.is_keyword(kw::Reuse) {465            return None;466        }467468        // no: `reuse ::path` for compatibility reasons with macro invocations469        if self.look_ahead(1, |t| t.is_path_start() && *t != token::PathSep) {470            Some(ReuseKind::Path)471        } else if self.check_impl_frontmatter(1) {472            Some(ReuseKind::Impl)473        } else {474            None475        }476    }477478    /// Are we sure this could not possibly be a macro invocation?479    fn isnt_macro_invocation(&mut self) -> bool {480        self.check_ident() && self.look_ahead(1, |t| *t != token::Bang && *t != token::PathSep)481    }482483    /// Recover on encountering a struct, enum, or method definition where the user484    /// forgot to add the `struct`, `enum`, or `fn` keyword485    fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {486        let is_pub = self.prev_token.is_keyword(kw::Pub);487        let is_const = self.prev_token.is_keyword(kw::Const);488        let ident_span = self.token.span;489        let span = if is_pub { self.prev_token.span.to(ident_span) } else { ident_span };490        let insert_span = ident_span.shrink_to_lo();491492        let ident = if self.token.is_ident()493            && (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))494            && self.look_ahead(1, |t| {495                matches!(t.kind, token::Lt | token::OpenBrace | token::OpenParen)496            }) {497            self.parse_ident_common(true).unwrap()498        } else {499            return Ok(());500        };501502        let mut found_generics = false;503        if self.check(exp!(Lt)) {504            found_generics = true;505            self.eat_to_tokens(&[exp!(Gt)]);506            self.bump(); // `>`507        }508509        let err = if self.check(exp!(OpenBrace)) {510            // possible struct or enum definition where `struct` or `enum` was forgotten511            if self.look_ahead(1, |t| *t == token::CloseBrace) {512                // `S {}` could be unit enum or struct513                Some(errors::MissingKeywordForItemDefinition::EnumOrStruct { span })514            } else if self.look_ahead(2, |t| *t == token::Colon)515                || self.look_ahead(3, |t| *t == token::Colon)516            {517                // `S { f:` or `S { pub f:`518                Some(errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident })519            } else {520                Some(errors::MissingKeywordForItemDefinition::Enum { span, insert_span, ident })521            }522        } else if self.check(exp!(OpenParen)) {523            // possible function or tuple struct definition where `fn` or `struct` was forgotten524            self.bump(); // `(`525            let is_method = self.recover_self_param();526527            self.consume_block(exp!(OpenParen), exp!(CloseParen), ConsumeClosingDelim::Yes);528529            let err = if self.check(exp!(RArrow)) || self.check(exp!(OpenBrace)) {530                self.eat_to_tokens(&[exp!(OpenBrace)]);531                self.bump(); // `{`532                self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes);533                if is_method {534                    errors::MissingKeywordForItemDefinition::Method { span, insert_span, ident }535                } else {536                    errors::MissingKeywordForItemDefinition::Function { span, insert_span, ident }537                }538            } else if is_pub && self.check(exp!(Semi)) {539                errors::MissingKeywordForItemDefinition::Struct { span, insert_span, ident }540            } else {541                errors::MissingKeywordForItemDefinition::Ambiguous {542                    span,543                    subdiag: if found_generics {544                        None545                    } else if let Ok(snippet) = self.span_to_snippet(ident_span) {546                        Some(errors::AmbiguousMissingKwForItemSub::SuggestMacro {547                            span: ident_span,548                            snippet,549                        })550                    } else {551                        Some(errors::AmbiguousMissingKwForItemSub::HelpMacro)552                    },553                }554            };555            Some(err)556        } else if found_generics {557            Some(errors::MissingKeywordForItemDefinition::Ambiguous { span, subdiag: None })558        } else {559            None560        };561562        if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }563    }564565    fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {566        // To be expanded567        Ok(None)568    }569570    /// Parses an item macro, e.g., `item!();`.571    fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {572        let path = self.parse_path(PathStyle::Mod)?; // `foo::bar`573        self.expect(exp!(Bang))?; // `!`574        match self.parse_delim_args() {575            // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.576            Ok(args) => {577                self.eat_semi_for_macro_if_needed(&args, Some(&path));578                self.complain_if_pub_macro(vis, false);579                Ok(MacCall { path, args })580            }581582            Err(mut err) => {583                // Maybe the user misspelled `macro_rules` (issue #91227)584                if self.token.is_ident()585                    && let [segment] = path.segments.as_slice()586                    && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()587                {588                    err.span_suggestion(589                        path.span,590                        "perhaps you meant to define a macro",591                        "macro_rules",592                        Applicability::MachineApplicable,593                    );594                }595                Err(err)596            }597        }598    }599600    /// Recover if we parsed attributes and expected an item but there was none.601    fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {602        let ([start @ end] | [start, .., end]) = attrs else {603            return Ok(());604        };605        let msg = if end.is_doc_comment() {606            "expected item after doc comment"607        } else {608            "expected item after attributes"609        };610        let mut err = self.dcx().struct_span_err(end.span, msg);611        if end.is_doc_comment() {612            err.span_label(end.span, "this doc comment doesn't document anything");613        } else if self.token == TokenKind::Semi {614            err.span_suggestion_verbose(615                self.token.span,616                "consider removing this semicolon",617                "",618                Applicability::MaybeIncorrect,619            );620        }621        if let [.., penultimate, _] = attrs {622            err.span_label(start.span.to(penultimate.span), "other attributes here");623        }624        Err(err)625    }626627    fn is_async_fn(&self) -> bool {628        self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])629    }630631    fn parse_polarity(&mut self) -> ast::ImplPolarity {632        // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.633        if self.check(exp!(Bang)) && self.look_ahead(1, |t| t.can_begin_type()) {634            self.psess.gated_spans.gate(sym::negative_impls, self.token.span);635            self.bump(); // `!`636            ast::ImplPolarity::Negative(self.prev_token.span)637        } else {638            ast::ImplPolarity::Positive639        }640    }641642    /// Parses an implementation item.643    ///644    /// ```ignore (illustrative)645    /// impl<'a, T> TYPE { /* impl items */ }646    /// impl<'a, T> TRAIT for TYPE { /* impl items */ }647    /// impl<'a, T> !TRAIT for TYPE { /* impl items */ }648    /// impl<'a, T> const TRAIT for TYPE { /* impl items */ }649    /// ```650    ///651    /// We actually parse slightly more relaxed grammar for better error reporting and recovery.652    /// ```ebnf653    /// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}"654    /// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}"655    /// ```656    fn parse_item_impl(657        &mut self,658        attrs: &mut AttrVec,659        defaultness: Defaultness,660        is_reuse: bool,661    ) -> PResult<'a, ItemKind> {662        let constness = self.parse_constness(Case::Sensitive);663        let safety = self.parse_safety(Case::Sensitive);664        self.expect_keyword(exp!(Impl))?;665666        // First, parse generic parameters if necessary.667        let mut generics = if self.choose_generics_over_qpath(0) {668            self.parse_generics()?669        } else {670            let mut generics = Generics::default();671            // impl A for B {}672            //    /\ this is where `generics.span` should point when there are no type params.673            generics.span = self.prev_token.span.shrink_to_hi();674            generics675        };676677        if let Const::Yes(span) = constness {678            self.psess.gated_spans.gate(sym::const_trait_impl, span);679        }680681        // Parse stray `impl async Trait`682        if (self.token_uninterpolated_span().at_least_rust_2018()683            && self.token.is_keyword(kw::Async))684            || self.is_kw_followed_by_ident(kw::Async)685        {686            self.bump();687            self.dcx().emit_err(errors::AsyncImpl { span: self.prev_token.span });688        }689690        let polarity = self.parse_polarity();691692        // Parse both types and traits as a type, then reinterpret if necessary.693        let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)694        {695            let span = self.prev_token.span.between(self.token.span);696            return Err(self.dcx().create_err(errors::MissingTraitInTraitImpl {697                span,698                for_span: span.to(self.token.span),699            }));700        } else {701            self.parse_ty_with_generics_recovery(&generics)?702        };703704        // If `for` is missing we try to recover.705        let has_for = self.eat_keyword(exp!(For));706        let missing_for_span = self.prev_token.span.between(self.token.span);707708        let ty_second = if self.token == token::DotDot {709            // We need to report this error after `cfg` expansion for compatibility reasons710            self.bump(); // `..`, do not add it to expected tokens711712            // AST validation later detects this `TyKind::Dummy` and emits an713            // error. (#121072 will hopefully remove all this special handling714            // of the obsolete `impl Trait for ..` and then this can go away.)715            Some(self.mk_ty(self.prev_token.span, TyKind::Dummy))716        } else if has_for || self.token.can_begin_type() {717            Some(self.parse_ty()?)718        } else {719            None720        };721722        generics.where_clause = self.parse_where_clause()?;723724        let impl_items = if is_reuse {725            Default::default()726        } else {727            self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?728        };729730        let (of_trait, self_ty) = match ty_second {731            Some(ty_second) => {732                // impl Trait for Type733                if !has_for {734                    self.dcx().emit_err(errors::MissingForInTraitImpl { span: missing_for_span });735                }736737                let ty_first = *ty_first;738                let path = match ty_first.kind {739                    // This notably includes paths passed through `ty` macro fragments (#46438).740                    TyKind::Path(None, path) => path,741                    other => {742                        if let TyKind::ImplTrait(_, bounds) = other743                            && let [bound] = bounds.as_slice()744                            && let GenericBound::Trait(poly_trait_ref) = bound745                        {746                            // Suggest removing extra `impl` keyword:747                            // `impl<T: Default> impl Default for Wrapper<T>`748                            //                   ^^^^^749                            let extra_impl_kw = ty_first.span.until(bound.span());750                            self.dcx().emit_err(errors::ExtraImplKeywordInTraitImpl {751                                extra_impl_kw,752                                impl_trait_span: ty_first.span,753                            });754                            poly_trait_ref.trait_ref.path.clone()755                        } else {756                            return Err(self.dcx().create_err(757                                errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span },758                            ));759                        }760                    }761                };762                let trait_ref = TraitRef { path, ref_id: ty_first.id };763764                let of_trait =765                    Some(Box::new(TraitImplHeader { defaultness, safety, polarity, trait_ref }));766                (of_trait, ty_second)767            }768            None => {769                let self_ty = ty_first;770                let error = |modifier, modifier_name, modifier_span| {771                    self.dcx().create_err(errors::TraitImplModifierInInherentImpl {772                        span: self_ty.span,773                        modifier,774                        modifier_name,775                        modifier_span,776                        self_ty: self_ty.span,777                    })778                };779780                if let Safety::Unsafe(span) = safety {781                    error("unsafe", "unsafe", span).with_code(E0197).emit();782                }783                if let ImplPolarity::Negative(span) = polarity {784                    error("!", "negative", span).emit();785                }786                if let Defaultness::Default(def_span) = defaultness {787                    error("default", "default", def_span).emit();788                }789                if let Const::Yes(span) = constness {790                    self.psess.gated_spans.gate(sym::const_trait_impl, span);791                }792                (None, self_ty)793            }794        };795796        Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness }))797    }798799    fn parse_item_delegation(800        &mut self,801        attrs: &mut AttrVec,802        defaultness: Defaultness,803        kind: ReuseKind,804    ) -> PResult<'a, ItemKind> {805        let span = self.token.span;806        self.expect_keyword(exp!(Reuse))?;807808        let item_kind = match kind {809            ReuseKind::Path => self.parse_path_like_delegation(),810            ReuseKind::Impl => self.parse_impl_delegation(span, attrs, defaultness),811        }?;812813        self.psess.gated_spans.gate(sym::fn_delegation, span.to(self.prev_token.span));814815        Ok(item_kind)816    }817818    fn parse_delegation_body(&mut self) -> PResult<'a, Option<Box<Block>>> {819        Ok(if self.check(exp!(OpenBrace)) {820            Some(self.parse_block()?)821        } else {822            self.expect(exp!(Semi))?;823            None824        })825    }826827    fn parse_impl_delegation(828        &mut self,829        span: Span,830        attrs: &mut AttrVec,831        defaultness: Defaultness,832    ) -> PResult<'a, ItemKind> {833        let mut impl_item = self.parse_item_impl(attrs, defaultness, true)?;834        let ItemKind::Impl(Impl { items, of_trait, .. }) = &mut impl_item else { unreachable!() };835836        let until_expr_span = span.to(self.prev_token.span);837838        let Some(of_trait) = of_trait else {839            return Err(self840                .dcx()841                .create_err(errors::ImplReuseInherentImpl { span: until_expr_span }));842        };843844        let body = self.parse_delegation_body()?;845        let whole_reuse_span = span.to(self.prev_token.span);846847        items.push(Box::new(AssocItem {848            id: DUMMY_NODE_ID,849            attrs: Default::default(),850            span: whole_reuse_span,851            tokens: None,852            vis: Visibility {853                kind: VisibilityKind::Inherited,854                span: whole_reuse_span,855                tokens: None,856            },857            kind: AssocItemKind::DelegationMac(Box::new(DelegationMac {858                qself: None,859                prefix: of_trait.trait_ref.path.clone(),860                suffixes: DelegationSuffixes::Glob(whole_reuse_span),861                body,862            })),863        }));864865        Ok(impl_item)866    }867868    fn parse_path_like_delegation(&mut self) -> PResult<'a, ItemKind> {869        let (qself, path) = if self.eat_lt() {870            let (qself, path) = self.parse_qpath(PathStyle::Expr)?;871            (Some(qself), path)872        } else {873            (None, self.parse_path(PathStyle::Expr)?)874        };875876        let rename = |this: &mut Self| {877            Ok(if this.eat_keyword(exp!(As)) { Some(this.parse_ident()?) } else { None })878        };879880        Ok(if self.eat_path_sep() {881            let suffixes = if self.eat(exp!(Star)) {882                DelegationSuffixes::Glob(self.prev_token.span)883            } else {884                let parse_suffix = |p: &mut Self| Ok((p.parse_path_segment_ident()?, rename(p)?));885                DelegationSuffixes::List(886                    self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0,887                )888            };889890            ItemKind::DelegationMac(Box::new(DelegationMac {891                qself,892                prefix: path,893                suffixes,894                body: self.parse_delegation_body()?,895            }))896        } else {897            let rename = rename(self)?;898            let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);899900            ItemKind::Delegation(Box::new(Delegation {901                id: DUMMY_NODE_ID,902                qself,903                path,904                ident,905                rename,906                body: self.parse_delegation_body()?,907                source: DelegationSource::Single,908            }))909        })910    }911912    fn parse_item_list<T>(913        &mut self,914        attrs: &mut AttrVec,915        mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,916    ) -> PResult<'a, ThinVec<T>> {917        let open_brace_span = self.token.span;918919        // Recover `impl Ty;` instead of `impl Ty {}`920        if self.token == TokenKind::Semi {921            self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });922            self.bump();923            return Ok(ThinVec::new());924        }925926        self.expect(exp!(OpenBrace))?;927        attrs.extend(self.parse_inner_attributes()?);928929        let mut items = ThinVec::new();930        while !self.eat(exp!(CloseBrace)) {931            if self.recover_doc_comment_before_brace() {932                continue;933            }934            self.recover_vcs_conflict_marker();935            match parse_item(self) {936                Ok(None) => {937                    let mut is_unnecessary_semicolon = !items.is_empty()938                        // When the close delim is `)` in a case like the following, `token.kind`939                        // is expected to be `token::CloseParen`, but the actual `token.kind` is940                        // `token::CloseBrace`. This is because the `token.kind` of the close delim941                        // is treated as the same as that of the open delim in942                        // `TokenTreesReader::parse_token_tree`, even if the delimiters of them are943                        // different. Therefore, `token.kind` should not be compared here.944                        //945                        // issue-60075.rs946                        // ```947                        // trait T {948                        //     fn qux() -> Option<usize> {949                        //         let _ = if true {950                        //         });951                        //          ^ this close delim952                        //         Some(4)953                        //     }954                        // ```955                        && self956                            .span_to_snippet(self.prev_token.span)957                            .is_ok_and(|snippet| snippet == "}")958                        && self.token == token::Semi;959                    let mut semicolon_span = self.token.span;960                    if !is_unnecessary_semicolon {961                        // #105369, Detect spurious `;` before assoc fn body962                        is_unnecessary_semicolon =963                            self.token == token::OpenBrace && self.prev_token == token::Semi;964                        semicolon_span = self.prev_token.span;965                    }966                    // We have to bail or we'll potentially never make progress.967                    let non_item_span = self.token.span;968                    let is_let = self.token.is_keyword(kw::Let);969970                    let mut err =971                        self.dcx().struct_span_err(non_item_span, "non-item in item list");972                    self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes);973                    if is_let {974                        err.span_suggestion_verbose(975                            non_item_span,976                            "consider using `const` instead of `let` for associated const",977                            "const",978                            Applicability::MachineApplicable,979                        );980                    } else {981                        err.span_label(open_brace_span, "item list starts here")982                            .span_label(non_item_span, "non-item starts here")983                            .span_label(self.prev_token.span, "item list ends here");984                    }985                    if is_unnecessary_semicolon {986                        err.span_suggestion(987                            semicolon_span,988                            "consider removing this semicolon",989                            "",990                            Applicability::MaybeIncorrect,991                        );992                    }993                    err.emit();994                    break;995                }996                Ok(Some(item)) => items.extend(item),997                Err(err) => {998                    self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes);999                    err.with_span_label(1000                        open_brace_span,1001                        "while parsing this item list starting here",1002                    )1003                    .with_span_label(self.prev_token.span, "the item list ends here")1004                    .emit();1005                    break;1006                }1007            }1008        }1009        Ok(items)1010    }10111012    /// Recover on a doc comment before `}`.1013    fn recover_doc_comment_before_brace(&mut self) -> bool {1014        if let token::DocComment(..) = self.token.kind {1015            if self.look_ahead(1, |tok| tok == &token::CloseBrace) {1016                // FIXME: merge with `DocCommentDoesNotDocumentAnything` (E0585)1017                struct_span_code_err!(1018                    self.dcx(),1019                    self.token.span,1020                    E0584,1021                    "found a documentation comment that doesn't document anything",1022                )1023                .with_span_label(self.token.span, "this doc comment doesn't document anything")1024                .with_help(1025                    "doc comments must come before what they document, if a comment was \1026                    intended use `//`",1027                )1028                .emit();1029                self.bump();1030                return true;1031            }1032        }1033        false1034    }10351036    /// Parses defaultness (i.e., `default` or nothing).1037    fn parse_defaultness(&mut self) -> Defaultness {1038        // We are interested in `default` followed by another identifier.1039        // However, we must avoid keywords that occur as binary operators.1040        // Currently, the only applicable keyword is `as` (`default as Ty`).1041        if self.check_keyword(exp!(Default))1042            && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))1043        {1044            self.psess.gated_spans.gate(sym::specialization, self.token.span);1045            self.bump(); // `default`1046            Defaultness::Default(self.prev_token_uninterpolated_span())1047        } else if self.eat_keyword(exp!(Final)) {1048            self.psess.gated_spans.gate(sym::final_associated_functions, self.prev_token.span);1049            Defaultness::Final(self.prev_token_uninterpolated_span())1050        } else {1051            Defaultness::Implicit1052        }1053    }10541055    /// Is this an `[impl(in? path)]? const? unsafe? auto? trait` item?1056    fn check_trait_front_matter(&mut self) -> bool {1057        const SUFFIXES: &[&[Symbol]] = &[1058            &[kw::Trait],1059            &[kw::Auto, kw::Trait],1060            &[kw::Unsafe, kw::Trait],1061            &[kw::Unsafe, kw::Auto, kw::Trait],1062            &[kw::Const, kw::Trait],1063            &[kw::Const, kw::Auto, kw::Trait],1064            &[kw::Const, kw::Unsafe, kw::Trait],1065            &[kw::Const, kw::Unsafe, kw::Auto, kw::Trait],1066        ];1067        // `impl(`1068        if self.check_keyword(exp!(Impl)) && self.look_ahead(1, |t| t == &token::OpenParen) {1069            // `impl(in` unambiguously introduces an `impl` restriction1070            if self.is_keyword_ahead(2, &[kw::In]) {1071                return true;1072            }1073            // `impl(crate | self | super)` + SUFFIX1074            if self.is_keyword_ahead(2, &[kw::Crate, kw::SelfLower, kw::Super])1075                && self.look_ahead(3, |t| t == &token::CloseParen)1076                && SUFFIXES.iter().any(|suffix| {1077                    suffix.iter().enumerate().all(|(i, kw)| self.is_keyword_ahead(i + 4, &[*kw]))1078                })1079            {1080                return true;1081            }1082            // Recover cases like `impl(path::to::module)` + SUFFIX to suggest inserting `in`.1083            SUFFIXES.iter().any(|suffix| {1084                suffix.iter().enumerate().all(|(i, kw)| {1085                    self.tree_look_ahead(i + 2, |t| {1086                        if let TokenTree::Token(token, _) = t {1087                            token.is_keyword(*kw)1088                        } else {1089                            false1090                        }1091                    })1092                    .unwrap_or(false)1093                })1094            })1095        } else {1096            SUFFIXES.iter().any(|suffix| {1097                suffix.iter().enumerate().all(|(i, kw)| {1098                    // We use `check_keyword` for the first token to include it in the expected tokens.1099                    if i == 0 {1100                        match *kw {1101                            kw::Const => self.check_keyword(exp!(Const)),1102                            kw::Unsafe => self.check_keyword(exp!(Unsafe)),1103                            kw::Auto => self.check_keyword(exp!(Auto)),1104                            kw::Trait => self.check_keyword(exp!(Trait)),1105                            _ => unreachable!(),1106                        }1107                    } else {1108                        self.is_keyword_ahead(i, &[*kw])1109                    }1110                })1111            })1112        }1113    }11141115    /// Parses `[impl(in? path)]? const? unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`.1116    fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {1117        let impl_restriction = self.parse_impl_restriction()?;1118        let constness = self.parse_constness(Case::Sensitive);1119        if let Const::Yes(span) = constness {1120            self.psess.gated_spans.gate(sym::const_trait_impl, span);1121        }1122        let safety = self.parse_safety(Case::Sensitive);1123        // Parse optional `auto` prefix.1124        let is_auto = if self.eat_keyword(exp!(Auto)) {1125            self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);1126            IsAuto::Yes1127        } else {1128            IsAuto::No1129        };11301131        self.expect_keyword(exp!(Trait))?;1132        let ident = self.parse_ident()?;1133        let mut generics = self.parse_generics()?;11341135        // Parse optional colon and supertrait bounds.1136        let had_colon = self.eat(exp!(Colon));1137        let span_at_colon = self.prev_token.span;1138        let bounds = if had_colon { self.parse_generic_bounds()? } else { Vec::new() };11391140        let span_before_eq = self.prev_token.span;1141        if self.eat(exp!(Eq)) {1142            // It's a trait alias.1143            if had_colon {1144                let span = span_at_colon.to(span_before_eq);1145                self.dcx().emit_err(errors::BoundsNotAllowedOnTraitAliases { span });1146            }11471148            let bounds = self.parse_generic_bounds()?;1149            generics.where_clause = self.parse_where_clause()?;1150            self.expect_semi()?;11511152            let whole_span = lo.to(self.prev_token.span);1153            if is_auto == IsAuto::Yes {1154                self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span });1155            }1156            if let Safety::Unsafe(_) = safety {1157                self.dcx().emit_err(errors::TraitAliasCannotBeUnsafe { span: whole_span });1158            }1159            if let RestrictionKind::Restricted { .. } = impl_restriction.kind {1160                self.dcx().emit_err(errors::TraitAliasCannotBeImplRestricted { span: whole_span });1161            }11621163            self.psess.gated_spans.gate(sym::trait_alias, whole_span);11641165            Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))1166        } else {1167            // It's a normal trait.1168            generics.where_clause = self.parse_where_clause()?;1169            let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;1170            Ok(ItemKind::Trait(Box::new(Trait {1171                impl_restriction,1172                constness,1173                is_auto,1174                safety,1175                ident,1176                generics,1177                bounds,1178                items,1179            })))1180        }1181    }11821183    pub fn parse_impl_item(1184        &mut self,1185        force_collect: ForceCollect,1186    ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {1187        let fn_parse_mode =1188            FnParseMode { req_name: |_, _| true, context: FnContext::Impl, req_body: true };1189        self.parse_assoc_item(fn_parse_mode, force_collect)1190    }11911192    pub fn parse_trait_item(1193        &mut self,1194        force_collect: ForceCollect,1195    ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {1196        let fn_parse_mode = FnParseMode {1197            req_name: |edition, _| edition >= Edition::Edition2018,1198            context: FnContext::Trait,1199            req_body: false,1200        };1201        self.parse_assoc_item(fn_parse_mode, force_collect)1202    }12031204    /// Parses associated items.1205    fn parse_assoc_item(1206        &mut self,1207        fn_parse_mode: FnParseMode,1208        force_collect: ForceCollect,1209    ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {1210        Ok(self1211            .parse_item_(1212                fn_parse_mode,1213                force_collect,1214                AllowConstBlockItems::DoesNotMatter, // due to `AssocItemKind::try_from` below1215            )?1216            .map(|Item { attrs, id, span, vis, kind, tokens }| {1217                let kind = match AssocItemKind::try_from(kind) {1218                    Ok(kind) => kind,1219                    Err(kind) => match kind {1220                        ItemKind::Static(StaticItem {1221                            ident,1222                            ty,1223                            safety: _,1224                            mutability: _,1225                            expr,1226                            define_opaque,1227                            eii_impls: _,1228                        }) => {1229                            self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });1230                            AssocItemKind::Const(Box::new(ConstItem {1231                                defaultness: Defaultness::Implicit,1232                                ident,1233                                generics: Generics::default(),1234                                ty,1235                                rhs_kind: ConstItemRhsKind::Body { rhs: expr },1236                                define_opaque,1237                            }))1238                        }1239                        _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),1240                    },1241                };1242                Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))1243            }))1244    }12451246    /// Parses a `type` alias with the following grammar:1247    /// ```ebnf1248    /// TypeAlias = "type" Ident Generics (":" GenericBounds)? WhereClause ("=" Ty)? WhereClause ";" ;1249    /// ```1250    /// The `"type"` has already been eaten.1251    fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {1252        let ident = self.parse_ident()?;1253        let mut generics = self.parse_generics()?;12541255        // Parse optional colon and param bounds.1256        let bounds = if self.eat(exp!(Colon)) { self.parse_generic_bounds()? } else { Vec::new() };1257        generics.where_clause = self.parse_where_clause()?;12581259        let ty = if self.eat(exp!(Eq)) { Some(self.parse_ty()?) } else { None };12601261        let after_where_clause = self.parse_where_clause()?;12621263        self.expect_semi()?;12641265        Ok(ItemKind::TyAlias(Box::new(TyAlias {1266            defaultness,1267            ident,1268            generics,1269            after_where_clause,1270            bounds,1271            ty,1272        })))1273    }12741275    /// Parses a `UseTree`.1276    ///1277    /// ```text1278    /// USE_TREE = [`::`] `*` |1279    ///            [`::`] `{` USE_TREE_LIST `}` |1280    ///            PATH `::` `*` |1281    ///            PATH `::` `{` USE_TREE_LIST `}` |1282    ///            PATH [`as` IDENT]1283    /// ```1284    fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {1285        let lo = self.token.span;12861287        let mut prefix =1288            ast::Path { segments: ThinVec::new(), span: lo.shrink_to_lo(), tokens: None };1289        let kind =1290            if self.check(exp!(OpenBrace)) || self.check(exp!(Star)) || self.is_import_coupler() {1291                // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`1292                let mod_sep_ctxt = self.token.span.ctxt();1293                if self.eat_path_sep() {1294                    prefix1295                        .segments1296                        .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));1297                }12981299                self.parse_use_tree_glob_or_nested()?1300            } else {1301                // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`1302                prefix = self.parse_path(PathStyle::Mod)?;13031304                if self.eat_path_sep() {1305                    self.parse_use_tree_glob_or_nested()?1306                } else {1307                    // Recover from using a colon as path separator.1308                    while self.eat_noexpect(&token::Colon) {1309                        self.dcx()1310                            .emit_err(errors::SingleColonImportPath { span: self.prev_token.span });13111312                        // We parse the rest of the path and append it to the original prefix.1313                        self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;1314                        prefix.span = lo.to(self.prev_token.span);1315                    }13161317                    UseTreeKind::Simple(self.parse_rename()?)1318                }1319            };13201321        Ok(UseTree { prefix, kind })1322    }13231324    /// Parses `*` or `{...}`.1325    fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {1326        Ok(if self.eat(exp!(Star)) {1327            UseTreeKind::Glob(self.prev_token.span)1328        } else {1329            let lo = self.token.span;1330            UseTreeKind::Nested {1331                items: self.parse_use_tree_list()?,1332                span: lo.to(self.prev_token.span),1333            }1334        })1335    }13361337    /// Parses a `UseTreeKind::Nested(list)`.1338    ///1339    /// ```text1340    /// USE_TREE_LIST = ∅ | (USE_TREE `,`)* USE_TREE [`,`]1341    /// ```1342    fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {1343        self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |p| {1344            p.recover_vcs_conflict_marker();1345            Ok((p.parse_use_tree()?, DUMMY_NODE_ID))1346        })1347        .map(|(r, _)| r)1348    }13491350    fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {1351        if self.eat_keyword(exp!(As)) {1352            self.parse_ident_or_underscore().map(Some)1353        } else {1354            Ok(None)1355        }1356    }13571358    fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {1359        match self.token.ident() {1360            Some((ident @ Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) => {1361                self.bump();1362                Ok(ident)1363            }1364            _ => self.parse_ident(),1365        }1366    }13671368    /// Parses `extern crate` links.1369    ///1370    /// # Examples1371    ///1372    /// ```ignore (illustrative)1373    /// extern crate foo;1374    /// extern crate bar as foo;1375    /// ```1376    fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {1377        // Accept `extern crate name-like-this` for better diagnostics1378        let orig_ident = self.parse_crate_name_with_dashes()?;1379        let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {1380            (Some(orig_ident.name), rename)1381        } else {1382            (None, orig_ident)1383        };1384        self.expect_semi()?;1385        Ok(ItemKind::ExternCrate(orig_name, item_ident))1386    }13871388    fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {1389        let ident = if self.token.is_keyword(kw::SelfLower) {1390            self.parse_path_segment_ident()1391        } else {1392            self.parse_ident()1393        }?;13941395        let dash = exp!(Minus);1396        if self.token != dash.tok {1397            return Ok(ident);1398        }13991400        // Accept `extern crate name-like-this` for better diagnostics.1401        let mut dashes = vec![];1402        let mut idents = vec![];1403        while self.eat(dash) {1404            dashes.push(self.prev_token.span);1405            idents.push(self.parse_ident()?);1406        }14071408        let fixed_name_sp = ident.span.to(idents.last().unwrap().span);1409        let mut fixed_name = ident.name.to_string();1410        for part in idents {1411            write!(fixed_name, "_{}", part.name).unwrap();1412        }14131414        self.dcx().emit_err(errors::ExternCrateNameWithDashes {1415            span: fixed_name_sp,1416            sugg: errors::ExternCrateNameWithDashesSugg { dashes },1417        });14181419        Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))1420    }14211422    /// Parses `extern` for foreign ABIs modules.1423    ///1424    /// `extern` is expected to have been consumed before calling this method.1425    ///1426    /// # Examples1427    ///1428    /// ```ignore (only-for-syntax-highlight)1429    /// extern "C" {}1430    /// extern {}1431    /// ```1432    fn parse_item_foreign_mod(1433        &mut self,1434        attrs: &mut AttrVec,1435        mut safety: Safety,1436    ) -> PResult<'a, ItemKind> {1437        let extern_span = self.prev_token_uninterpolated_span();1438        let abi = self.parse_abi(); // ABI?1439        // FIXME: This recovery should be tested better.1440        if safety == Safety::Default1441            && self.token.is_keyword(kw::Unsafe)1442            && self.look_ahead(1, |t| *t == token::OpenBrace)1443        {1444            self.expect(exp!(OpenBrace)).unwrap_err().emit();1445            safety = Safety::Unsafe(self.token.span);1446            let _ = self.eat_keyword(exp!(Unsafe));1447        }1448        Ok(ItemKind::ForeignMod(ast::ForeignMod {1449            extern_span,1450            safety,1451            abi,1452            items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,1453        }))1454    }14551456    /// Parses a foreign item (one in an `extern { ... }` block).1457    pub fn parse_foreign_item(1458        &mut self,1459        force_collect: ForceCollect,1460    ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {1461        let fn_parse_mode = FnParseMode {1462            req_name: |_, is_dot_dot_dot| is_dot_dot_dot == IsDotDotDot::No,1463            context: FnContext::Free,1464            req_body: false,1465        };1466        Ok(self1467            .parse_item_(1468                fn_parse_mode,1469                force_collect,1470                AllowConstBlockItems::DoesNotMatter, // due to `ForeignItemKind::try_from` below1471            )?1472            .map(|Item { attrs, id, span, vis, kind, tokens }| {1473                let kind = match ForeignItemKind::try_from(kind) {1474                    Ok(kind) => kind,1475                    Err(kind) => match kind {1476                        ItemKind::Const(ConstItem { ident, ty, rhs_kind, .. }) => {1477                            let const_span = Some(span.with_hi(ident.span.lo()))1478                                .filter(|span| span.can_be_used_for_suggestions());1479                            self.dcx().emit_err(errors::ExternItemCannotBeConst {1480                                ident_span: ident.span,1481                                const_span,1482                            });1483                            ForeignItemKind::Static(Box::new(StaticItem {1484                                ident,1485                                ty,1486                                mutability: Mutability::Not,1487                                expr: match rhs_kind {1488                                    ConstItemRhsKind::Body { rhs } => rhs,1489                                    ConstItemRhsKind::TypeConst { rhs: Some(anon) } => {1490                                        Some(anon.value)1491                                    }1492                                    ConstItemRhsKind::TypeConst { rhs: None } => None,1493                                },1494                                safety: Safety::Default,1495                                define_opaque: None,1496                                eii_impls: ThinVec::default(),1497                            }))1498                        }1499                        _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),1500                    },1501                };1502                Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))1503            }))1504    }15051506    fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {1507        // FIXME(#100717): needs variant for each `ItemKind` (instead of using `ItemKind::descr()`)1508        let span = self.psess.source_map().guess_head_span(span);1509        let descr = kind.descr();1510        let help = match kind {1511            ItemKind::DelegationMac(DelegationMac {1512                suffixes: DelegationSuffixes::Glob(_),1513                ..1514            }) => false,1515            _ => true,1516        };1517        self.dcx().emit_err(errors::BadItemKind { span, descr, ctx, help });1518        None1519    }15201521    fn is_use_closure(&self) -> bool {1522        if self.token.is_keyword(kw::Use) {1523            // Check if this could be a closure.1524            self.look_ahead(1, |token| {1525                // Move or Async here would be an error but still we're parsing a closure1526                let dist =1527                    if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };15281529                self.look_ahead(dist, |token| matches!(token.kind, token::Or | token::OrOr))1530            })1531        } else {1532            false1533        }1534    }15351536    fn is_unsafe_foreign_mod(&self) -> bool {1537        // Look for `unsafe`.1538        if !self.token.is_keyword(kw::Unsafe) {1539            return false;1540        }1541        // Look for `extern`.1542        if !self.is_keyword_ahead(1, &[kw::Extern]) {1543            return false;1544        }15451546        // Look for the optional ABI string literal.1547        let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };15481549        // Look for the `{`. Use `tree_look_ahead` because the ABI (if present)1550        // might be a metavariable i.e. an invisible-delimited sequence, and1551        // `tree_look_ahead` will consider that a single element when looking1552        // ahead.1553        self.tree_look_ahead(n, |t| matches!(t, TokenTree::Delimited(_, _, Delimiter::Brace, _)))1554            == Some(true)1555    }15561557    fn parse_global_static_front_matter(&mut self, case: Case) -> Option<Safety> {1558        let is_global_static = if self.check_keyword_case(exp!(Static), case) {1559            // Check if this could be a closure.1560            !self.look_ahead(1, |token| {1561                if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) {1562                    return true;1563                }1564                matches!(token.kind, token::Or | token::OrOr)1565            })1566        } else {1567            // `$qual static`1568            (self.check_keyword_case(exp!(Unsafe), case)1569                || self.check_keyword_case(exp!(Safe), case))1570                && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case))1571        };15721573        if is_global_static {1574            let safety = self.parse_safety(case);1575            let _ = self.eat_keyword_case(exp!(Static), case);1576            Some(safety)1577        } else {1578            None1579        }1580    }15811582    /// Recover on `const mut` with `const` already eaten.1583    fn recover_const_mut(&mut self, const_span: Span) {1584        if self.eat_keyword(exp!(Mut)) {1585            let span = self.prev_token.span;1586            self.dcx()1587                .emit_err(errors::ConstGlobalCannotBeMutable { ident_span: span, const_span });1588        } else if self.eat_keyword(exp!(Let)) {1589            let span = self.prev_token.span;1590            self.dcx().emit_err(errors::ConstLetMutuallyExclusive { span: const_span.to(span) });1591        }1592    }15931594    fn parse_const_block_item(&mut self) -> PResult<'a, ConstBlockItem> {1595        self.expect_keyword(exp!(Const))?;1596        let const_span = self.prev_token.span;1597        self.psess.gated_spans.gate(sym::const_block_items, const_span);1598        let block = self.parse_block()?;1599        Ok(ConstBlockItem { id: DUMMY_NODE_ID, span: const_span.to(block.span), block })1600    }16011602    /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in1603    /// `mutability`.1604    ///1605    /// ```ebnf1606    /// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;1607    /// ```1608    fn parse_static_item(1609        &mut self,1610        safety: Safety,1611        mutability: Mutability,1612    ) -> PResult<'a, ItemKind> {1613        let ident = self.parse_ident()?;16141615        if self.token == TokenKind::Lt && self.may_recover() {1616            let generics = self.parse_generics()?;1617            self.dcx().emit_err(errors::StaticWithGenerics { span: generics.span });1618        }16191620        // Parse the type of a static item. That is, the `":" $ty` fragment.1621        // FIXME: This could maybe benefit from `.may_recover()`?1622        let ty = match (self.eat(exp!(Colon)), self.check(exp!(Eq)) | self.check(exp!(Semi))) {1623            (true, false) => self.parse_ty()?,1624            // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing1625            // type.1626            (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),1627        };16281629        let expr = if self.eat(exp!(Eq)) { Some(self.parse_expr()?) } else { None };16301631        self.expect_semi()?;16321633        let item = StaticItem {1634            ident,1635            ty,1636            safety,1637            mutability,1638            expr,1639            define_opaque: None,1640            eii_impls: ThinVec::default(),1641        };1642        Ok(ItemKind::Static(Box::new(item)))1643    }16441645    /// Parse a constant item with the prefix `"const"` already parsed.1646    ///1647    /// If `const_arg` is true, any expression assigned to the const will be parsed1648    /// as a const_arg instead of a body expression.1649    ///1650    /// ```ebnf1651    /// Const = "const" ($ident | "_") Generics ":" $ty (= $expr)? WhereClause ";" ;1652    /// ```1653    fn parse_const_item(1654        &mut self,1655        const_arg: bool,1656        const_span: Span,1657    ) -> PResult<'a, (Ident, Generics, Box<Ty>, ConstItemRhsKind)> {1658        let ident = self.parse_ident_or_underscore()?;16591660        let mut generics = self.parse_generics()?;16611662        // Check the span for emptiness instead of the list of parameters in order to correctly1663        // recognize and subsequently flag empty parameter lists (`<>`) as unstable.1664        if !generics.span.is_empty() {1665            self.psess.gated_spans.gate(sym::generic_const_items, generics.span);1666        }16671668        // Parse the type of a constant item. That is, the `":" $ty` fragment.1669        // FIXME: This could maybe benefit from `.may_recover()`?1670        let ty = match (1671            self.eat(exp!(Colon)),1672            self.check(exp!(Eq)) | self.check(exp!(Semi)) | self.check_keyword(exp!(Where)),1673        ) {1674            (true, false) => self.parse_ty()?,1675            // If there wasn't a `:` or the colon was followed by a `=`, `;` or `where`, recover a missing type.1676            (colon, _) => self.recover_missing_global_item_type(colon, None),1677        };16781679        // Proactively parse a where-clause to be able to provide a good error message in case we1680        // encounter the item body following it.1681        let before_where_clause =1682            if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };16831684        let rhs = match (self.eat(exp!(Eq)), const_arg) {1685            (true, true) => ConstItemRhsKind::TypeConst {1686                rhs: Some(self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?),1687            },1688            (true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) },1689            (false, true) => ConstItemRhsKind::TypeConst { rhs: None },1690            (false, false) => ConstItemRhsKind::Body { rhs: None },1691        };16921693        let after_where_clause = self.parse_where_clause()?;16941695        // Provide a nice error message if the user placed a where-clause before the item body.1696        // Users may be tempted to write such code if they are still used to the deprecated1697        // where-clause location on type aliases and associated types. See also #89122.1698        if before_where_clause.has_where_token1699            && let Some(rhs_span) = rhs.span()1700        {1701            self.dcx().emit_err(errors::WhereClauseBeforeConstBody {1702                span: before_where_clause.span,1703                name: ident.span,1704                body: rhs_span,1705                sugg: if !after_where_clause.has_where_token {1706                    self.psess.source_map().span_to_snippet(rhs_span).ok().map(|body_s| {1707                        errors::WhereClauseBeforeConstBodySugg {1708                            left: before_where_clause.span.shrink_to_lo(),1709                            snippet: body_s,1710                            right: before_where_clause.span.shrink_to_hi().to(rhs_span),1711                        }1712                    })1713                } else {1714                    // FIXME(generic_const_items): Provide a structured suggestion to merge the first1715                    // where-clause into the second one.1716                    None1717                },1718            });1719        }17201721        // Merge the predicates of both where-clauses since either one can be relevant.1722        // If we didn't parse a body (which is valid for associated consts in traits) and we were1723        // allowed to recover, `before_where_clause` contains the predicates, otherwise they are1724        // in `after_where_clause`. Further, both of them might contain predicates iff two1725        // where-clauses were provided which is syntactically ill-formed but we want to recover from1726        // it and treat them as one large where-clause.1727        let mut predicates = before_where_clause.predicates;1728        predicates.extend(after_where_clause.predicates);1729        let where_clause = WhereClause {1730            has_where_token: before_where_clause.has_where_token1731                || after_where_clause.has_where_token,1732            predicates,1733            span: if after_where_clause.has_where_token {1734                after_where_clause.span1735            } else {1736                before_where_clause.span1737            },1738        };17391740        if where_clause.has_where_token {1741            self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);1742        }17431744        generics.where_clause = where_clause;17451746        if let Some(rhs) = self.try_recover_const_missing_semi(&rhs, const_span) {1747            return Ok((ident, generics, ty, ConstItemRhsKind::Body { rhs: Some(rhs) }));1748        }1749        self.expect_semi()?;17501751        Ok((ident, generics, ty, rhs))1752    }17531754    /// We were supposed to parse `":" $ty` but the `:` or the type was missing.1755    /// This means that the type is missing.1756    fn recover_missing_global_item_type(1757        &mut self,1758        colon_present: bool,1759        m: Option<Mutability>,1760    ) -> Box<Ty> {1761        // Construct the error and stash it away with the hope1762        // that typeck will later enrich the error with a type.1763        let kind = match m {1764            Some(Mutability::Mut) => "static mut",1765            Some(Mutability::Not) => "static",1766            None => "const",1767        };17681769        let colon = match colon_present {1770            true => "",1771            false => ":",1772        };17731774        let span = self.prev_token.span.shrink_to_hi();1775        let err = self.dcx().create_err(errors::MissingConstType { span, colon, kind });1776        err.stash(span, StashKey::ItemNoType);17771778        // The user intended that the type be inferred,1779        // so treat this as if the user wrote e.g. `const A: _ = expr;`.1780        Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None })1781    }17821783    /// Parses an enum declaration.1784    fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {1785        if self.token.is_keyword(kw::Struct) {1786            let span = self.prev_token.span.to(self.token.span);1787            let err = errors::EnumStructMutuallyExclusive { span };1788            if self.look_ahead(1, |t| t.is_ident()) {1789                self.bump();1790                self.dcx().emit_err(err);1791            } else {1792                return Err(self.dcx().create_err(err));1793            }1794        }17951796        let prev_span = self.prev_token.span;1797        let ident = self.parse_ident()?;1798        let mut generics = self.parse_generics()?;1799        generics.where_clause = self.parse_where_clause()?;18001801        // Possibly recover `enum Foo;` instead of `enum Foo {}`1802        let (variants, _) = if self.token == TokenKind::Semi {1803            self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });1804            self.bump();1805            (thin_vec![], Trailing::No)1806        } else {1807            self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |p| {1808                p.parse_enum_variant(ident.span)1809            })1810            .map_err(|mut err| {1811                err.span_label(ident.span, "while parsing this enum");1812                // Try to recover `enum Foo { ident : Ty }`.1813                if self.prev_token.is_non_reserved_ident() && self.token == token::Colon {1814                    let snapshot = self.create_snapshot_for_diagnostic();1815                    self.bump();1816                    match self.parse_ty() {1817                        Ok(_) => {1818                            err.span_suggestion_verbose(1819                                prev_span,1820                                "perhaps you meant to use `struct` here",1821                                "struct",1822                                Applicability::MaybeIncorrect,1823                            );1824                        }1825                        Err(e) => {1826                            e.cancel();1827                        }1828                    }1829                    self.restore_snapshot(snapshot);1830                }1831                self.eat_to_tokens(&[exp!(CloseBrace)]);1832                self.bump(); // }1833                err1834            })?1835        };18361837        let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };1838        Ok(ItemKind::Enum(ident, generics, enum_definition))1839    }18401841    fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {1842        self.recover_vcs_conflict_marker();1843        let variant_attrs = self.parse_outer_attributes()?;1844        self.recover_vcs_conflict_marker();1845        let help = "enum variants can be `Variant`, `Variant = <integer>`, \1846                    `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`";1847        self.collect_tokens(None, variant_attrs, ForceCollect::No, |this, variant_attrs| {1848            let vlo = this.token.span;18491850            let vis = this.parse_visibility(FollowedByType::No)?;1851            if !this.recover_nested_adt_item(kw::Enum)? {1852                return Ok((None, Trailing::No, UsePreAttrPos::No));1853            }1854            let ident = this.parse_field_ident("enum", vlo)?;18551856            if this.token == token::Bang {1857                if let Err(err) = this.unexpected() {1858                    err.with_note(msg!("macros cannot expand to enum variants")).emit();1859                }18601861                this.bump();1862                this.parse_delim_args()?;18631864                return Ok((None, Trailing::from(this.token == token::Comma), UsePreAttrPos::No));1865            }18661867            let struct_def = if this.check(exp!(OpenBrace)) {1868                // Parse a struct variant.1869                let (fields, recovered) =1870                    match this.parse_record_struct_body("struct", ident.span, false) {1871                        Ok((fields, recovered)) => (fields, recovered),1872                        Err(mut err) => {1873                            if this.token == token::Colon {1874                                // We handle `enum` to `struct` suggestion in the caller.1875                                return Err(err);1876                            }1877                            this.eat_to_tokens(&[exp!(CloseBrace)]);1878                            this.bump(); // }1879                            err.span_label(span, "while parsing this enum");1880                            err.help(help);1881                            let guar = err.emit();1882                            (thin_vec![], Recovered::Yes(guar))1883                        }1884                    };1885                VariantData::Struct { fields, recovered }1886            } else if this.check(exp!(OpenParen)) {1887                let body = match this.parse_tuple_struct_body() {1888                    Ok(body) => body,1889                    Err(mut err) => {1890                        if this.token == token::Colon {1891                            // We handle `enum` to `struct` suggestion in the caller.1892                            return Err(err);1893                        }1894                        this.eat_to_tokens(&[exp!(CloseParen)]);1895                        this.bump(); // )1896                        err.span_label(span, "while parsing this enum");1897                        err.help(help);1898                        err.emit();1899                        thin_vec![]1900                    }1901                };1902                VariantData::Tuple(body, DUMMY_NODE_ID)1903            } else {1904                VariantData::Unit(DUMMY_NODE_ID)1905            };19061907            let disr_expr = if this.eat(exp!(Eq)) {1908                Some(this.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?)1909            } else {1910                None1911            };19121913            let span = vlo.to(this.prev_token.span);1914            if ident.name == kw::Underscore {1915                this.psess.gated_spans.gate(sym::unnamed_enum_variants, span);1916            }1917            let vr = ast::Variant {1918                ident,1919                vis,1920                id: DUMMY_NODE_ID,1921                attrs: variant_attrs,1922                data: struct_def,1923                disr_expr,1924                span,1925                is_placeholder: false,1926            };19271928            Ok((Some(vr), Trailing::from(this.token == token::Comma), UsePreAttrPos::No))1929        })1930        .map_err(|mut err| {1931            err.help(help);1932            err1933        })1934    }19351936    /// Parses `struct Foo { ... }`.1937    fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {1938        let ident = self.parse_ident()?;19391940        let mut generics = self.parse_generics()?;19411942        // There is a special case worth noting here, as reported in issue #17904.1943        // If we are parsing a tuple struct it is the case that the where clause1944        // should follow the field list. Like so:1945        //1946        // struct Foo<T>(T) where T: Copy;1947        //1948        // If we are parsing a normal record-style struct it is the case1949        // that the where clause comes before the body, and after the generics.1950        // So if we look ahead and see a brace or a where-clause we begin1951        // parsing a record style struct.1952        //1953        // Otherwise if we look ahead and see a paren we parse a tuple-style1954        // struct.19551956        let vdata = if self.token.is_keyword(kw::Where) {1957            let tuple_struct_body;1958            (generics.where_clause, tuple_struct_body) =1959                self.parse_struct_where_clause(ident, generics.span)?;19601961            if let Some(body) = tuple_struct_body {1962                // If we see a misplaced tuple struct body: `struct Foo<T> where T: Copy, (T);`1963                let body = VariantData::Tuple(body, DUMMY_NODE_ID);1964                self.expect_semi()?;1965                body1966            } else if self.eat(exp!(Semi)) {1967                // If we see a: `struct Foo<T> where T: Copy;` style decl.1968                VariantData::Unit(DUMMY_NODE_ID)1969            } else {1970                // If we see: `struct Foo<T> where T: Copy { ... }`1971                let (fields, recovered) = self.parse_record_struct_body(1972                    "struct",1973                    ident.span,1974                    generics.where_clause.has_where_token,1975                )?;1976                VariantData::Struct { fields, recovered }1977            }1978        // No `where` so: `struct Foo<T>;`1979        } else if self.eat(exp!(Semi)) {1980            VariantData::Unit(DUMMY_NODE_ID)1981        // Record-style struct definition1982        } else if self.token == token::OpenBrace {1983            let (fields, recovered) = self.parse_record_struct_body(1984                "struct",1985                ident.span,1986                generics.where_clause.has_where_token,1987            )?;1988            VariantData::Struct { fields, recovered }1989        // Tuple-style struct definition with optional where-clause.1990        } else if self.token == token::OpenParen {1991            let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);1992            generics.where_clause = self.parse_where_clause()?;1993            self.expect_semi()?;1994            body1995        } else {1996            let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token);1997            return Err(self.dcx().create_err(err));1998        };19992000        Ok(ItemKind::Struct(ident, generics, vdata))

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.