Skip to main content

rustc_parse/parser/
ty.rs

1use rustc_ast::token::{self, IdentKind, MetaVarKind, Token, TokenKind};
2use rustc_ast::util::case::Case;
3use rustc_ast::{
4    self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy,
5    GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, Mutability, Path,
6    Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
7    TyKind, UnsafeBinderTy,
8};
9use rustc_errors::{Applicability, Diag, E0516, PResult};
10use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
11use thin_vec::{ThinVec, thin_vec};
12
13use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
14use crate::diagnostics::{
15    self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
16    FnPtrWithGenerics, FnPtrWithGenericsSugg, HelpUseLatestEdition, InvalidCVariadicType,
17    InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,
18    ReturnTypesUseThinArrow,
19};
20use crate::parser::{FnContext, FnParseMode, FrontMatterParsingMode};
21use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
22
23/// Signals whether parsing a type should allow `+`.
24///
25/// For example, let T be the type `impl Default + 'static`
26/// With `AllowPlus::Yes`, T will be parsed successfully
27/// With `AllowPlus::No`, parsing T will return a parse error
28#[derive(#[automatically_derived]impl ::core::marker::Copy for AllowPlus { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for AllowPlus {
}
#[automatically_derived]impl ::core::clone::Clone for AllowPlus {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::StructuralPartialEq for AllowPlus
    {
}
#[automatically_derived]impl ::core::cmp::PartialEq for AllowPlus {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq)]
29pub(super) enum AllowPlus {
30    Yes,
31    No,
32}
33
34#[derive(#[automatically_derived]impl ::core::marker::StructuralPartialEq for
    RecoverQPath {
}
#[automatically_derived]impl ::core::cmp::PartialEq for RecoverQPath {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq)]
35pub(super) enum RecoverQPath {
36    Yes,
37    No,
38}
39
40pub(super) enum RecoverQuestionMark {
41    Yes,
42    No,
43}
44
45/// Signals whether parsing a type should recover `->`.
46///
47/// More specifically, when parsing a function like:
48/// ```compile_fail
49/// fn foo() => u8 { 0 }
50/// fn bar(): u8 { 0 }
51/// ```
52/// The compiler will try to recover interpreting `foo() => u8` as `foo() -> u8` when calling
53/// `parse_ty` with anything except `RecoverReturnSign::No`, and it will try to recover `bar(): u8`
54/// as `bar() -> u8` when passing `RecoverReturnSign::Yes` to `parse_ty`
55#[derive(#[automatically_derived]impl ::core::marker::Copy for RecoverReturnSign { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for RecoverReturnSign {
}
#[automatically_derived]impl ::core::clone::Clone for RecoverReturnSign {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    RecoverReturnSign {
}
#[automatically_derived]impl ::core::cmp::PartialEq for RecoverReturnSign {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq)]
56pub(super) enum RecoverReturnSign {
57    Yes,
58    OnlyFatArrow,
59    No,
60}
61
62impl RecoverReturnSign {
63    /// [RecoverReturnSign::Yes] allows for recovering `fn foo() => u8` and `fn foo(): u8`,
64    /// [RecoverReturnSign::OnlyFatArrow] allows for recovering only `fn foo() => u8` (recovering
65    /// colons can cause problems when parsing where clauses), and
66    /// [RecoverReturnSign::No] doesn't allow for any recovery of the return type arrow
67    fn can_recover(self, token: &TokenKind) -> bool {
68        match self {
69            Self::Yes => #[allow(non_exhaustive_omitted_patterns)] match token {
    token::FatArrow | token::Colon => true,
    _ => false,
}matches!(token, token::FatArrow | token::Colon),
70            Self::OnlyFatArrow => #[allow(non_exhaustive_omitted_patterns)] match token {
    token::FatArrow => true,
    _ => false,
}matches!(token, token::FatArrow),
71            Self::No => false,
72        }
73    }
74}
75
76// Is `...` (`CVarArgs`) legal at this level of type parsing?
77#[derive(#[automatically_derived]impl ::core::marker::StructuralPartialEq for
    AllowCVariadic {
}
#[automatically_derived]impl ::core::cmp::PartialEq for AllowCVariadic {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq)]
78enum AllowCVariadic {
79    Yes,
80    No,
81}
82
83/// Determine if the given token can begin a bound assuming it follows Rust 2015 identifier `dyn`.
84///
85/// In Rust 2015, `dyn` is a contextual keyword, not a full one.
86fn can_begin_dyn_bound_in_rust_2015(t: Token) -> bool {
87    // In `dyn::x`, `dyn<X>` and `dyn<<X>::Y>`, `dyn` should (continue to) denote a regular path
88    // segment for backward compatibility. We make an exception for `dyn(X)` which used to be
89    // interpreted as a path with parenthesized generic arguments which can be semantically
90    // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait
91    // object type whose first bound is parenthesized.
92
93    // Contrary to `Parser::can_begin_bound`, `!`, `const`, `[` and `async` are deliberately not
94    // part of this list to contain the number of potential regressions esp. in MBE code.
95    // `const` and `[` would regress UI test `macro-dyn-const-2015.rs` and
96    // `!` would regress `dyn!(...)` macro calls in Rust 2015 for example.
97
98    if t.is_path_start() {
99        return t != token::PathSep && t != token::Lt && t != token::Shl;
100    }
101
102    t == token::OpenParen || t == token::Question || t.is_lifetime() || t.is_keyword(kw::For)
103}
104
105impl<'a> Parser<'a> {
106    /// Parses a type.
107    pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {
108        if self.token == token::DotDotDot {
109            // We special case this so that we don't talk about "nested C-variadics" in types.
110            // We still pass in `AllowCVariadic::No` so that `parse_ty_common` can complain about
111            // things like `Vec<...>`.
112            let span = self.token.span;
113            self.bump();
114            let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));
115            return Ok(self.mk_ty(span, kind));
116        }
117        self.parse_ty_common(
118            AllowPlus::Yes,
119            AllowCVariadic::No,
120            RecoverQPath::Yes,
121            RecoverReturnSign::Yes,
122            None,
123            RecoverQuestionMark::Yes,
124        )
125    }
126
127    pub(super) fn parse_ty_with_generics_recovery(
128        &mut self,
129        ty_params: &Generics,
130    ) -> PResult<'a, Box<Ty>> {
131        self.parse_ty_common(
132            AllowPlus::Yes,
133            AllowCVariadic::No,
134            RecoverQPath::Yes,
135            RecoverReturnSign::Yes,
136            Some(ty_params),
137            RecoverQuestionMark::Yes,
138        )
139    }
140
141    /// Parse a type suitable for a function or function pointer parameter.
142    /// The difference from `parse_ty` is that this version allows `...`
143    /// (`CVarArgs`) at the top level of the type.
144    pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, Box<Ty>> {
145        let ty = self.parse_ty_common(
146            AllowPlus::Yes,
147            AllowCVariadic::Yes,
148            RecoverQPath::Yes,
149            RecoverReturnSign::Yes,
150            None,
151            RecoverQuestionMark::Yes,
152        )?;
153
154        // Recover a trailing `= EXPR` if present.
155        if self.may_recover()
156            && self.check_noexpect(&token::Eq)
157            && self.look_ahead(1, |tok| tok.can_begin_expr())
158        {
159            let snapshot = self.create_snapshot_for_diagnostic();
160            self.bump();
161            let eq_span = self.prev_token.span;
162            match self.parse_expr() {
163                Ok(e) => {
164                    self.dcx()
165                        .struct_span_err(eq_span.to(e.span), "parameter defaults are not supported")
166                        .emit();
167                }
168                Err(diag) => {
169                    diag.cancel();
170                    self.restore_snapshot(snapshot);
171                }
172            }
173        }
174
175        Ok(ty)
176    }
177
178    /// Parses a type in restricted contexts where `+` is not permitted.
179    ///
180    /// Example 1: `&'a TYPE`
181    ///     `+` is prohibited to maintain operator priority (P(+) < P(&)).
182    /// Example 2: `value1 as TYPE + value2`
183    ///     `+` is prohibited to avoid interactions with expression grammar.
184    pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, Box<Ty>> {
185        self.parse_ty_common(
186            AllowPlus::No,
187            AllowCVariadic::No,
188            RecoverQPath::Yes,
189            RecoverReturnSign::Yes,
190            None,
191            RecoverQuestionMark::Yes,
192        )
193    }
194
195    /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin
196    /// for better diagnostics involving `?`.
197    pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, Box<Ty>> {
198        self.parse_ty_common(
199            AllowPlus::No,
200            AllowCVariadic::No,
201            RecoverQPath::Yes,
202            RecoverReturnSign::Yes,
203            None,
204            RecoverQuestionMark::No,
205        )
206    }
207
208    pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, Box<Ty>> {
209        self.parse_ty_common(
210            AllowPlus::Yes,
211            AllowCVariadic::No,
212            RecoverQPath::Yes,
213            RecoverReturnSign::Yes,
214            None,
215            RecoverQuestionMark::No,
216        )
217    }
218
219    /// Parse a type without recovering `:` as `->` to avoid breaking code such
220    /// as `where fn() : for<'a>`.
221    pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, Box<Ty>> {
222        self.parse_ty_common(
223            AllowPlus::Yes,
224            AllowCVariadic::No,
225            RecoverQPath::Yes,
226            RecoverReturnSign::OnlyFatArrow,
227            None,
228            RecoverQuestionMark::Yes,
229        )
230    }
231
232    /// Parses an optional return type `[ -> TY ]` in a function declaration.
233    pub(super) fn parse_ret_ty(
234        &mut self,
235        allow_plus: AllowPlus,
236        recover_qpath: RecoverQPath,
237        recover_return_sign: RecoverReturnSign,
238    ) -> PResult<'a, FnRetTy> {
239        let lo = self.prev_token.span;
240        let ate_arrow = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::RArrow,
    token_type: crate::parser::token_type::TokenType::RArrow,
}exp!(RArrow)) {
241            true
242        } else if recover_return_sign.can_recover(&self.token.kind) {
243            // Don't `eat` to prevent `=>` from being added as an expected token which isn't
244            // actually expected and could only confuse users
245            self.bump();
246            self.dcx().emit_err(ReturnTypesUseThinArrow {
247                span: self.prev_token.span,
248                suggestion: lo.between(self.token.span),
249            });
250            true
251        } else {
252            false
253        };
254
255        Ok(if ate_arrow {
256            FnRetTy::Ty(
257                // FIXME(Centril): Can we unconditionally `allow_plus`?
258                match self.parse_ty_common(
259                    allow_plus,
260                    AllowCVariadic::No,
261                    recover_qpath,
262                    recover_return_sign,
263                    None,
264                    RecoverQuestionMark::Yes,
265                ) {
266                    Ok(ty) => ty,
267                    Err(e) if self.may_recover() => {
268                        while !#[allow(non_exhaustive_omitted_patterns)] match self.token.kind {
    TokenKind::OpenBrace | TokenKind::CloseBrace | TokenKind::Semi |
        TokenKind::Eof => true,
    _ => false,
}matches!(
269                            self.token.kind,
270                            TokenKind::OpenBrace
271                                | TokenKind::CloseBrace
272                                | TokenKind::Semi
273                                | TokenKind::Eof
274                        ) {
275                            self.bump();
276                        }
277                        // only emit the recovered type if the end of the type actually was found
278                        if self.token.kind == TokenKind::Eof {
279                            return Err(e);
280                        }
281                        self.mk_ty(self.prev_token.span, TyKind::Err(e.emit_err()))
282                    }
283                    Err(e) => return Err(e),
284                },
285            )
286        } else {
287            FnRetTy::Default(self.prev_token.span.shrink_to_hi())
288        })
289    }
290
291    fn parse_ty_common(
292        &mut self,
293        allow_plus: AllowPlus,
294        allow_c_variadic: AllowCVariadic,
295        recover_qpath: RecoverQPath,
296        recover_return_sign: RecoverReturnSign,
297        ty_generics: Option<&Generics>,
298        recover_question_mark: RecoverQuestionMark,
299    ) -> PResult<'a, Box<Ty>> {
300        let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
301        if allow_qpath_recovery && self.may_recover() &&
                let Some(mv_kind) = self.token.is_metavar_seq() &&
            let token::MetaVarKind::Ty { .. } = mv_kind &&
        self.check_noexpect_past_close_delim(&token::PathSep) {
    let ty =
        self.eat_metavar_seq(mv_kind,
                |this|
                    this.parse_ty_no_question_mark_recover()).expect("metavar seq ty");
    return self.maybe_recover_from_bad_qpath_stage_2(self.prev_token.span,
            ty);
};maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
302
303        if let Some(ty) = self.eat_metavar_seq_with_matcher(
304            |mv_kind| #[allow(non_exhaustive_omitted_patterns)] match mv_kind {
    MetaVarKind::Ty { .. } => true,
    _ => false,
}matches!(mv_kind, MetaVarKind::Ty { .. }),
305            |this| this.parse_ty_no_question_mark_recover(),
306        ) {
307            return Ok(ty);
308        }
309
310        self.recover_from_outer_attributes("types")?;
311
312        let lo = self.token.span;
313        let mut impl_dyn_multi = false;
314        let kind = if self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenParen,
    token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
315            self.parse_paren_start_ty(lo, allow_plus)?
316        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Bang,
    token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
317            // Never type `!`
318            TyKind::Never
319        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Star,
    token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
320            self.parse_ty_ptr()?
321        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenBracket,
    token_type: crate::parser::token_type::TokenType::OpenBracket,
}exp!(OpenBracket)) {
322            self.parse_array_or_slice_ty()?
323        } else if self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::And,
    token_type: crate::parser::token_type::TokenType::And,
}exp!(And)) || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::AndAnd,
    token_type: crate::parser::token_type::TokenType::AndAnd,
}exp!(AndAnd)) {
324            // Reference
325            self.expect_and()?;
326            self.parse_borrowed_pointee()?
327        } else if self.eat_keyword_noexpect(kw::Typeof) {
328            self.parse_typeof_ty(lo)?
329        } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Underscore,
    token_type: crate::parser::token_type::TokenType::KwUnderscore,
}exp!(Underscore)) {
330            // A type to be inferred `_`
331            TyKind::Infer
332        } else if self.check_fn_front_matter(false, Case::Sensitive) {
333            // Function pointer type
334            self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?
335        } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::For,
    token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For)) {
336            // Function pointer type or bound list (trait object type) starting with a poly-trait.
337            //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
338            //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
339            let (bound_vars, _) = self.parse_higher_ranked_binder()?;
340            if self.check_fn_front_matter(false, Case::Sensitive) {
341                self.parse_ty_fn_ptr(
342                    lo,
343                    bound_vars,
344                    Some(self.prev_token.span.shrink_to_lo()),
345                    recover_return_sign,
346                )?
347            } else {
348                // Try to recover `for<'a> dyn Trait` or `for<'a> impl Trait`.
349                if self.may_recover()
350                    && (self.token.is_keyword(kw::Impl) || self.can_begin_dyn_ty())
351                {
352                    self.bump();
353                    let (kw, _) = self.prev_token.ident().unwrap();
354                    let removal_span = kw.span.with_hi(self.token.span.lo());
355                    let path = self.parse_path(PathStyle::Type)?;
356                    let mut bounds = {
    let len = [()].len();
    let mut vec = ::thin_vec::ThinVec::with_capacity(len);
    vec.push(GenericBound::Trait(PolyTraitRef::new(bound_vars, path,
                TraitBoundModifiers::NONE, lo.to(self.prev_token.span),
                ast::Parens::No)));
    vec
}thin_vec![GenericBound::Trait(PolyTraitRef::new(
357                        bound_vars,
358                        path,
359                        TraitBoundModifiers::NONE,
360                        lo.to(self.prev_token.span),
361                        ast::Parens::No,
362                    ))];
363                    if allow_plus == AllowPlus::Yes && self.check_plus() {
364                        self.eat_plus();
365                        bounds.append(&mut self.parse_generic_bounds()?);
366                    }
367                    self.dcx().emit_err(diagnostics::TransposeDynOrImpl {
368                        span: kw.span,
369                        kw: kw.name.as_str(),
370                        sugg: diagnostics::TransposeDynOrImplSugg {
371                            removal_span,
372                            insertion_span: lo.shrink_to_lo(),
373                            kw: kw.name.as_str(),
374                        },
375                    });
376                    match kw.name {
377                        kw::Dyn => TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn),
378                        kw::Impl => TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds),
379                        _ => ::core::panicking::unreachable_default_msg()unreachable!(),
380                    }
381                } else {
382                    let path = self.parse_path(PathStyle::Type)?;
383                    let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
384                    self.finish_parsing_bare_trait_object_ty(
385                        bound_vars,
386                        path,
387                        lo,
388                        parse_plus,
389                        ast::Parens::No,
390                    )?
391                }
392            }
393        } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Impl,
    token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl)) {
394            self.parse_impl_ty(&mut impl_dyn_multi)?
395        } else if self.can_begin_dyn_ty() {
396            self.parse_dyn_ty(&mut impl_dyn_multi)?
397        } else if self.eat_lt() {
398            // Qualified path
399            let (qself, path) = self.parse_qpath(PathStyle::Type)?;
400            TyKind::Path(Some(qself), path)
401        } else if (self.token.is_keyword(kw::Const) || self.token.is_keyword(kw::Mut))
402            && self.look_ahead(1, |t| *t == token::Star)
403        {
404            self.parse_ty_c_style_pointer()?
405        } else if self.check_path() {
406            self.parse_path_start_ty(lo, allow_plus, ty_generics)?
407        } else if self.can_begin_bound() {
408            self.parse_bare_trait_object_ty(lo, allow_plus)?
409        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::DotDotDot,
    token_type: crate::parser::token_type::TokenType::DotDotDot,
}exp!(DotDotDot)) {
410            match allow_c_variadic {
411                AllowCVariadic::Yes => TyKind::CVarArgs,
412                AllowCVariadic::No => {
413                    // FIXME(c_variadic): Should we just allow `...` syntactically
414                    // anywhere in a type and use semantic restrictions instead?
415                    // NOTE: This may regress certain MBE calls if done incorrectly.
416                    let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });
417                    TyKind::Err(guar)
418                }
419            }
420        } 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))
421            && self.look_ahead(1, |tok| tok.kind == token::Lt)
422        {
423            self.parse_unsafe_binder_ty()?
424        } else if self.eat_forced_keyword_noexpect(kw::FieldOf) {
425            self.parse_ty_field_of(lo)?
426        } else {
427            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected type, found {0}",
                super::token_descr(&self.token)))
    })format!("expected type, found {}", super::token_descr(&self.token));
428            let mut err = self.dcx().struct_span_err(lo, msg);
429            err.span_label(lo, "expected type");
430            if self.may_recover()
431                && (self.eat_keyword_noexpect(kw::True) || self.eat_keyword_noexpect(kw::False))
432            {
433                err.span_suggestion(
434                    self.prev_token.span,
435                    "the type is called",
436                    "bool",
437                    Applicability::MachineApplicable,
438                );
439                err.emit();
440                TyKind::Path(
441                    None,
442                    Path::from_ident(Ident { span: self.prev_token.span, name: sym::bool }),
443                )
444            } else {
445                return Err(err);
446            }
447        };
448
449        let span = lo.to(self.prev_token.span);
450        let mut ty = self.mk_ty(span, kind);
451
452        // Try to recover from use of `+` with incorrect priority.
453        match allow_plus {
454            AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
455            AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
456        }
457        if let RecoverQuestionMark::Yes = recover_question_mark {
458            ty = self.maybe_recover_from_question_mark(ty);
459        }
460        if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
461    }
462
463    fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
464        let lo = self.token.span;
465        if !self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
                kw: rustc_span::symbol::kw::Unsafe,
                token_type: crate::parser::token_type::TokenType::KwUnsafe,
            }) {
    ::core::panicking::panic("assertion failed: self.eat_keyword(exp!(Unsafe))")
};assert!(self.eat_keyword(exp!(Unsafe)));
466        self.expect_lt()?;
467        let generic_params = self.parse_generic_params()?;
468        self.expect_gt()?;
469        let inner_ty = self.parse_ty()?;
470        let span = lo.to(self.prev_token.span);
471        self.psess.gated_spans.gate(sym::unsafe_binders, span);
472
473        Ok(TyKind::UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, inner_ty })))
474    }
475
476    /// Parse a type that begins with an opening parenthesis `(`.
477    ///
478    /// More specifically, it parses one of the following:
479    ///
480    /// 1. parenthesized type
481    /// 2. tuple type
482    /// 3. bare trait object type where the first trait bound is parenthesized
483    fn parse_paren_start_ty(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
484        let mut inside_has_trailing_plus = false;
485        let (ts, trailing_comma) = self.parse_paren_comma_seq(|p| {
486            let ty = p.parse_ty()?;
487            inside_has_trailing_plus = p.prev_token == TokenKind::Plus;
488            Ok(ty)
489        })?;
490
491        if ts.len() == 1 && #[allow(non_exhaustive_omitted_patterns)] match trailing_comma {
    Trailing::No => true,
    _ => false,
}matches!(trailing_comma, Trailing::No) {
492            let ty = ts.into_iter().next().unwrap();
493
494            // Let's check if we actually have a bare trait object type where the first trait bound
495            // is parenthesized. That's the case if the parentheses are followed by a `+` and if
496            // what's contained between the parentheses resembles a *BareTraitBound*.
497            //
498            // For context, looking at bounds in general (see *Bound*), only trait bounds are
499            // allowed to be wrapped in parentheses, not however outlives and use bounds.
500            let outside_has_eligible_trailing_plus =
501                allow_plus == AllowPlus::Yes && self.token.is_like_plus();
502            match ty.kind {
503                // `"(" TypePath ")" "+"`
504                TyKind::Path(None, path) if outside_has_eligible_trailing_plus => self
505                    .finish_parsing_bare_trait_object_ty(
506                        ThinVec::new(),
507                        path,
508                        lo,
509                        true,
510                        ast::Parens::Yes,
511                    ),
512                // `"(" BareTraitBound\TypePath ")" "+"`
513                //
514                // We actually accept outlives bounds here, too, purely to reduce diagnostic output
515                // for ill-formed code like `('a)+`: We know for a fact that the `parse_ty` above
516                // has already emitted an error for the inner `'a` as it's not followed by `+`.
517                // This way we indirectly suppress unhelpful follow-up diagnostics like E0178
518                // ("bad `+` in type") and E0224 ("no trait bound in trait object type").
519                TyKind::TraitObject(mut bounds, TraitObjectSyntax::None)
520                    if outside_has_eligible_trailing_plus
521                        && !inside_has_trailing_plus
522                        && let [ast::GenericBound::Trait(_) | ast::GenericBound::Outlives(_)] =
523                            bounds.as_slice() =>
524                {
525                    self.eat_plus();
526                    bounds.append(&mut self.parse_generic_bounds()?);
527                    Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
528                }
529                _ => Ok(TyKind::Paren(ty)),
530            }
531        } else {
532            Ok(TyKind::Tup(ts))
533        }
534    }
535
536    fn parse_bare_trait_object_ty(
537        &mut self,
538        lo: Span,
539        allow_plus: AllowPlus,
540    ) -> PResult<'a, TyKind> {
541        // A lifetime only begins a bare trait object type if it is followed by `+`!
542        if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
543            // In Rust 2021 and beyond, we assume that the user didn't intend to write a bare trait
544            // object type with a leading lifetime bound since that seems very unlikely given the
545            // fact that `dyn`-less trait objects are *semantically* invalid.
546            if self.psess.edition.at_least_rust_2021() {
547                let lt = self.expect_lifetime();
548                let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
549                err.span_label(lo, "expected type");
550                return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
551                    Ok(ref_ty) => ref_ty,
552                    Err(err) => TyKind::Err(err.emit_err()),
553                });
554            }
555
556            self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
557                span: lo,
558                suggestion: lo.shrink_to_hi(),
559            });
560        }
561        Ok(TyKind::TraitObject(
562            self.parse_generic_bounds_common(allow_plus)?,
563            TraitObjectSyntax::None,
564        ))
565    }
566
567    pub(super) fn parse_ref_ty_no_leading_ampersand(&mut self) -> (Mutability, Option<Box<Ty>>) {
568        let mutbl = self.parse_mutability();
569        match self.parse_ty_no_plus() {
570            Ok(ty) => (mutbl, Some(ty)),
571            Err(err) => {
572                err.cancel();
573                (mutbl, None)
574            }
575        }
576    }
577
578    fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
579        &mut self,
580        lt: Lifetime,
581        lo: Span,
582        mut err: Diag<'cx>,
583    ) -> Result<TyKind, Diag<'cx>> {
584        if !self.may_recover() {
585            return Err(err);
586        }
587        let snapshot = self.create_snapshot_for_diagnostic();
588        match self.parse_ref_ty_no_leading_ampersand() {
589            (_, None) => {
590                self.restore_snapshot(snapshot);
591                Err(err)
592            }
593            (mutbl, Some(ty)) => {
594                err.span_suggestion_verbose(
595                    lo.shrink_to_lo(),
596                    "you might have meant to write a reference type here",
597                    "&",
598                    Applicability::MaybeIncorrect,
599                );
600                err.emit();
601                Ok(TyKind::Ref(Some(lt), ty, mutbl))
602            }
603        }
604    }
605
606    fn finish_parsing_bare_trait_object_ty(
607        &mut self,
608        generic_params: ThinVec<GenericParam>,
609        path: ast::Path,
610        lo: Span,
611        parse_plus: bool,
612        parens: ast::Parens,
613    ) -> PResult<'a, TyKind> {
614        let mut bounds = {
    let len = [()].len();
    let mut vec = ::thin_vec::ThinVec::with_capacity(len);
    vec.push(GenericBound::Trait(PolyTraitRef::new(generic_params, path,
                TraitBoundModifiers::NONE, lo.to(self.prev_token.span),
                parens)));
    vec
}thin_vec![GenericBound::Trait(PolyTraitRef::new(
615            generic_params,
616            path,
617            TraitBoundModifiers::NONE,
618            lo.to(self.prev_token.span),
619            parens,
620        ))];
621        if parse_plus {
622            self.eat_plus();
623            bounds.append(&mut self.parse_generic_bounds()?);
624        }
625        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
626    }
627
628    /// Parses a raw pointer with a C-style typo
629    fn parse_ty_c_style_pointer(&mut self) -> PResult<'a, TyKind> {
630        let kw_span = self.token.span;
631        let mutbl = self.parse_mut_or_const();
632
633        if let Some(mutbl) = mutbl
634            && self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Star,
    token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star))
635        {
636            let star_span = self.prev_token.span;
637
638            let mutability = match mutbl {
639                Mutability::Not => "const",
640                Mutability::Mut => "mut",
641            };
642
643            let ty = self.parse_ty_no_question_mark_recover()?;
644
645            self.dcx()
646                .struct_span_err(
647                    kw_span,
648                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("raw pointer types must be written as `*{0} T`",
                mutability))
    })format!("raw pointer types must be written as `*{mutability} T`"),
649                )
650                .with_multipart_suggestion(
651                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("put the `*` before `{0}`",
                mutability))
    })format!("put the `*` before `{mutability}`"),
652                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(star_span, String::new()),
                (kw_span.shrink_to_lo(), "*".to_string())]))vec![(star_span, String::new()), (kw_span.shrink_to_lo(), "*".to_string())],
653                    Applicability::MachineApplicable,
654                )
655                .emit();
656
657            return Ok(TyKind::Ptr(ty, mutbl));
658        }
659        // This is unreachable because we always get into if above and return from it
660        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("this could never happen")));
}unreachable!("this could never happen")
661    }
662
663    /// Parses a raw pointer type: `*[const | mut] $type`.
664    fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
665        let mutbl = self.parse_mut_or_const().unwrap_or_else(|| {
666            let span = self.prev_token.span;
667            self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {
668                span,
669                after_asterisk: span.shrink_to_hi(),
670            });
671            Mutability::Not
672        });
673        let ty = self.parse_ty_no_plus()?;
674        Ok(TyKind::Ptr(ty, mutbl))
675    }
676
677    /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
678    /// The opening `[` bracket is already eaten.
679    fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
680        let elt_ty = self.parse_ty()?;
681
682        let ty = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Semi,
    token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
683            let mut length = self.parse_expr_anon_const()?;
684
685            if let Err(e) = self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseBracket,
    token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket)) {
686                // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
687                self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
688                self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseBracket,
    token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket))?;
689            }
690            TyKind::Array(elt_ty, length)
691        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseBracket,
    token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket)) {
692            TyKind::Slice(elt_ty)
693        } else {
694            self.maybe_recover_array_ty_without_semi(elt_ty)?
695        };
696
697        Ok(ty)
698    }
699
700    /// Recover from malformed array type syntax.
701    ///
702    /// This method attempts to recover from cases like:
703    /// - `[u8, 5]` → suggests using `;`, return a Array type
704    /// - `[u8 5]` → suggests using `;`, return a Array type
705    /// Consider to add more cases in the future.
706    fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: Box<Ty>) -> PResult<'a, TyKind> {
707        let span = self.token.span;
708        let token_descr = super::token_descr(&self.token);
709        let mut err =
710            self.dcx().struct_span_err(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected `;` or `]`, found {0}",
                token_descr))
    })format!("expected `;` or `]`, found {}", token_descr));
711        err.span_label(span, "expected `;` or `]`");
712
713        // If we cannot recover, return the error immediately.
714        if !self.may_recover() {
715            return Err(err);
716        }
717
718        let snapshot = self.create_snapshot_for_diagnostic();
719
720        // Consume common erroneous separators.
721        let hi = self.prev_token.span.hi();
722        _ = self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma)) || self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Colon,
    token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) || self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Star,
    token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star));
723        let suggestion_span = self.prev_token.span.with_lo(hi);
724
725        // FIXME(mgca): recovery is broken for `const {` args
726        // we first try to parse pattern like `[u8 5]`
727        let length = match self.parse_expr_anon_const() {
728            Ok(length) => length,
729            Err(e) => {
730                e.cancel();
731                self.restore_snapshot(snapshot);
732                return Err(err);
733            }
734        };
735
736        if let Err(e) = self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseBracket,
    token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket)) {
737            e.cancel();
738            self.restore_snapshot(snapshot);
739            return Err(err);
740        }
741
742        err.span_suggestion_verbose(
743            suggestion_span,
744            "you might have meant to use `;` as the separator",
745            ";",
746            Applicability::MaybeIncorrect,
747        );
748        err.emit();
749        Ok(TyKind::Array(elt_ty, length))
750    }
751
752    fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
753        let and_span = self.prev_token.span;
754        let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
755        let (pinned, mut mutbl) = self.parse_pin_and_mut();
756        if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
757            // A lifetime is invalid here: it would be part of a bare trait bound, which requires
758            // it to be followed by a plus, but we disallow plus in the pointee type.
759            // So we can handle this case as an error here, and suggest `'a mut`.
760            // If there *is* a plus next though, handling the error later provides better suggestions
761            // (like adding parentheses)
762            if !self.look_ahead(1, |t| t.is_like_plus()) {
763                let lifetime_span = self.token.span;
764                let span = and_span.to(lifetime_span);
765
766                let (suggest_lifetime, snippet) =
767                    if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
768                        (Some(span), lifetime_src)
769                    } else {
770                        (None, String::new())
771                    };
772                self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
773
774                opt_lifetime = Some(self.expect_lifetime());
775            }
776        } else if self.token.is_keyword(kw::Dyn)
777            && mutbl == Mutability::Not
778            && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
779        {
780            // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
781            let span = and_span.to(self.look_ahead(1, |t| t.span));
782            self.dcx().emit_err(DynAfterMut { span });
783
784            // Recovery
785            mutbl = Mutability::Mut;
786            let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
787            self.bump();
788            self.bump_with((dyn_tok, dyn_tok_sp));
789        }
790        let ty = self.parse_ty_no_plus()?;
791        Ok(match pinned {
792            Pinnedness::Not => TyKind::Ref(opt_lifetime, ty, mutbl),
793            Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, ty, mutbl),
794        })
795    }
796
797    /// Parse nothing, mutability or `pin` followed by "explicit" mutability.
798    ///
799    /// ```ebnf
800    /// PinAndMut = "pin" MutOrConst | "mut"
801    /// ```
802    pub(crate) fn parse_pin_and_mut(&mut self) -> (Pinnedness, Mutability) {
803        if self.token.is_keyword(kw::Pin) && self.look_ahead(1, Token::is_mutability) {
804            self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
805            if !self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
                kw: rustc_span::symbol::kw::Pin,
                token_type: crate::parser::token_type::TokenType::KwMut,
            }) {
    ::core::panicking::panic("assertion failed: self.eat_keyword(exp!(Pin))")
};assert!(self.eat_keyword(exp!(Pin)));
806            let mutbl = self.parse_mut_or_const().unwrap();
807            (Pinnedness::Pinned, mutbl)
808        } else {
809            (Pinnedness::Not, self.parse_mutability())
810        }
811    }
812
813    /// Parses the `typeof(EXPR)` for better diagnostics before returning
814    /// an error type.
815    fn parse_typeof_ty(&mut self, lo: Span) -> PResult<'a, TyKind> {
816        self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenParen,
    token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen))?;
817        let _expr = self.parse_expr_anon_const()?;
818        self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
819        let span = lo.to(self.prev_token.span);
820        let guar = self
821            .dcx()
822            .struct_span_err(span, "`typeof` is a reserved keyword but unimplemented")
823            .with_note("consider replacing `typeof(...)` with an actual type")
824            .with_code(E0516)
825            .emit_err();
826        Ok(TyKind::Err(guar))
827    }
828
829    pub(crate) fn parse_ty_field_of(&mut self, lo: Span) -> PResult<'a, TyKind> {
830        self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenParen,
    token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen))?;
831
832        let container = self.parse_ty()?;
833        self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma))?;
834
835        let fields = self.parse_floating_field_access()?;
836        let trailing_comma = self.eat_noexpect(&TokenKind::Comma);
837
838        if let Err(mut e) = self.expect_one_of(&[], &[crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]) {
839            if trailing_comma {
840                e.note("unexpected third argument to `field_of`");
841            } else {
842                e.note("`field_of` expects dot-separated field and variant names");
843            }
844            e.emit();
845        }
846
847        // Eat tokens until the construct ends.
848        if self.may_recover() {
849            while !self.token.kind.is_close_delim_or_eof() {
850                self.bump();
851            }
852        }
853
854        // FIXME: Odd not to include the closing paren (contrary to the leading one etc.) but
855        //        it actually "improves" diagnostics slightly by not pointing into the wrapper macros.
856        let span = self.token.span;
857        self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
858
859        self.psess.gated_spans.gate(sym::internal_syntax, lo.to(self.token.span));
860
861        match *fields {
862            [] => Err(self
863                .dcx()
864                .struct_span_err(span, "`field_of` expects dot-separated field and variant names")),
865            [field] => Ok(TyKind::FieldOf(container, None, field)),
866            [variant, field] => Ok(TyKind::FieldOf(container, Some(variant), field)),
867            _ => Err(self.dcx().struct_span_err(
868                fields.iter().map(|f| f.span).collect::<Vec<_>>(),
869                "`field_of` only supports a single field or a variant with a field",
870            )),
871        }
872    }
873
874    /// Parses a function pointer type (`TyKind::FnPtr`).
875    /// ```ignore (illustrative)
876    ///    [unsafe] [extern "ABI"] fn (S) -> T
877    /// //  ^~~~~^          ^~~~^     ^~^    ^
878    /// //    |               |        |     |
879    /// //    |               |        |   Return type
880    /// // Function Style    ABI  Parameter types
881    /// ```
882    /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
883    fn parse_ty_fn_ptr(
884        &mut self,
885        lo: Span,
886        mut params: ThinVec<GenericParam>,
887        param_insertion_point: Option<Span>,
888        recover_return_sign: RecoverReturnSign,
889    ) -> PResult<'a, TyKind> {
890        let inherited_vis = rustc_ast::Visibility {
891            span: rustc_span::DUMMY_SP,
892            kind: rustc_ast::VisibilityKind::Inherited,
893        };
894        let span_start = self.token.span;
895        let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(
896            &inherited_vis,
897            Case::Sensitive,
898            FrontMatterParsingMode::FunctionPtrType,
899        )?;
900        if self.may_recover() && self.token == TokenKind::Lt {
901            self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
902        }
903        let mode = crate::parser::FnParseMode {
904            req_name: |_, _| false,
905            context: FnContext::FunctionPtrType,
906            req_body: false,
907            allow_const_params: false,
908        };
909        let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;
910        let decl = Box::new(decl);
911
912        let decl_span = span_start.to(self.prev_token.span);
913        Ok(TyKind::FnPtr(Box::new(FnPtrTy {
914            ext,
915            safety,
916            generic_params: params,
917            decl,
918            decl_span,
919        })))
920    }
921
922    /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).
923    fn recover_fn_ptr_with_generics(
924        &mut self,
925        lo: Span,
926        params: &mut ThinVec<GenericParam>,
927        param_insertion_point: Option<Span>,
928    ) -> PResult<'a, ()> {
929        let generics = self.parse_generics()?;
930        let arity = generics.params.len();
931
932        let mut lifetimes: ThinVec<_> = generics
933            .params
934            .into_iter()
935            .filter(|param| #[allow(non_exhaustive_omitted_patterns)] match param.kind {
    ast::GenericParamKind::Lifetime => true,
    _ => false,
}matches!(param.kind, ast::GenericParamKind::Lifetime))
936            .collect();
937
938        let sugg = if !lifetimes.is_empty() {
939            let snippet =
940                lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
941
942            let (left, snippet) = if let Some(span) = param_insertion_point {
943                (span, if params.is_empty() { snippet } else { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {0}", snippet))
    })format!(", {snippet}") })
944            } else {
945                (lo.shrink_to_lo(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("for<{0}> ", snippet))
    })format!("for<{snippet}> "))
946            };
947
948            Some(FnPtrWithGenericsSugg {
949                left,
950                snippet,
951                right: generics.span,
952                arity,
953                for_param_list_exists: param_insertion_point.is_some(),
954            })
955        } else {
956            None
957        };
958
959        self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });
960        params.append(&mut lifetimes);
961        Ok(())
962    }
963
964    /// Parses an `impl B0 + ... + Bn` type.
965    fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
966        // If we encounter a type like `impl 'a Sized`, suggest `impl 'a + Sized`.
967        if self.token.is_lifetime()
968            && let Some(ident) = self.look_ahead(1, |t| t.non_reserved_ident())
969        {
970            self.dcx().emit_err(diagnostics::MissingPlusBounds {
971                span: self.token.span,
972                hi: self.token.span.shrink_to_hi(),
973                sym: ident.name,
974            });
975        }
976
977        // Always parse bounds greedily for better error recovery.
978        let bounds = self.parse_generic_bounds()?;
979
980        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
981
982        Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
983    }
984
985    /// Parse a use-bound aka precise capturing list.
986    ///
987    /// ```ebnf
988    /// UseBound = "use" "<" (PreciseCapture ("," PreciseCapture)* ","?)? ">"
989    /// PreciseCapture = "Self" | Ident | Lifetime
990    /// ```
991    fn parse_use_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
992        self.expect_lt()?;
993        let (args, _, _) = self.parse_seq_to_before_tokens(
994            &[crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Gt,
    token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)],
995            &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
996            SeqSep::trailing_allowed(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma)),
997            |self_| {
998                if self_.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::SelfUpper,
    token_type: crate::parser::token_type::TokenType::KwSelfUpper,
}exp!(SelfUpper)) {
999                    self_.bump();
1000                    Ok(PreciseCapturingArg::Arg(
1001                        ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
1002                        DUMMY_NODE_ID,
1003                    ))
1004                } else if self_.check_ident() {
1005                    Ok(PreciseCapturingArg::Arg(
1006                        ast::Path::from_ident(self_.parse_ident()?),
1007                        DUMMY_NODE_ID,
1008                    ))
1009                } else if self_.check_lifetime() {
1010                    Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
1011                } else {
1012                    self_.unexpected_any()
1013                }
1014            },
1015        )?;
1016        self.expect_gt()?;
1017
1018        if let ast::Parens::Yes = parens {
1019            self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1020            self.report_parenthesized_bound(lo, self.prev_token.span, "precise capturing lists");
1021        }
1022
1023        Ok(GenericBound::Use(args, lo.to(self.prev_token.span)))
1024    }
1025
1026    /// Can the current token begin a `dyn`-prefixed trait object type?
1027    fn can_begin_dyn_ty(&mut self) -> bool {
1028        self.token.is_keyword(kw::Dyn)
1029            && (self.token_uninterpolated_span().at_least_rust_2018()
1030                || self.look_ahead(1, |&t| can_begin_dyn_bound_in_rust_2015(t)))
1031    }
1032
1033    /// Parse a `dyn`-prefixed trait object type.
1034    fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
1035        self.bump(); // `dyn`
1036
1037        // Always parse bounds greedily for better error recovery.
1038        let bounds = self.parse_generic_bounds()?;
1039        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
1040
1041        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn))
1042    }
1043
1044    /// Parse a type that begins with a path.
1045    ///
1046    /// This can be:
1047    /// 1. a type macro, `mac!(...)`,
1048    /// 2. a bare trait object type, `B0 + ... + Bn`,
1049    /// 3. or a path, `path::to::MyType`.
1050    fn parse_path_start_ty(
1051        &mut self,
1052        lo: Span,
1053        allow_plus: AllowPlus,
1054        ty_generics: Option<&Generics>,
1055    ) -> PResult<'a, TyKind> {
1056        // Simple path
1057        let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
1058        if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Bang,
    token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
1059            // Macro invocation in type position
1060            Ok(TyKind::MacCall(Box::new(MacCall { path, args: self.parse_delim_args()? })))
1061        } else if allow_plus == AllowPlus::Yes && self.check_plus() {
1062            // `Trait1 + Trait2 + 'a`
1063            self.finish_parsing_bare_trait_object_ty(
1064                ThinVec::new(),
1065                path,
1066                lo,
1067                true,
1068                ast::Parens::No,
1069            )
1070        } else {
1071            // Just a type path.
1072            Ok(TyKind::Path(None, path))
1073        }
1074    }
1075
1076    pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
1077        self.parse_generic_bounds_common(AllowPlus::Yes)
1078    }
1079
1080    /// Parse generic bounds.
1081    ///
1082    /// Only if `allow_plus` this parses a `+`-separated list of bounds (trailing `+` is admitted).
1083    /// Otherwise, this only parses a single bound or none.
1084    fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
1085        let mut bounds = ThinVec::new();
1086
1087        // In addition to looping while we find generic bounds:
1088        // We continue even if we find a keyword. This is necessary for error recovery on,
1089        // for example, `impl fn()`. The only keyword that can go after generic bounds is
1090        // `where`, so stop if it's it.
1091        // We also continue if we find types (not traits), again for error recovery.
1092        while self.can_begin_bound()
1093            || (self.may_recover()
1094                && (self.token.can_begin_type()
1095                    || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
1096        {
1097            // Account for `&dyn Trait + dyn Other`.
1098            if self.can_begin_dyn_ty() {
1099                self.bump();
1100                self.dcx().emit_err(InvalidDynKeyword {
1101                    span: self.prev_token.span,
1102                    suggestion: self.prev_token.span.until(self.token.span),
1103                });
1104            }
1105            bounds.push(self.parse_generic_bound()?);
1106            if allow_plus == AllowPlus::No || !self.eat_plus() {
1107                break;
1108            }
1109        }
1110
1111        Ok(bounds)
1112    }
1113
1114    /// Can the current token begin a bound?
1115    fn can_begin_bound(&mut self) -> bool {
1116        // NOTE: Tokens `!`, `~`, `const` & `async` which represent the start of currently unstable
1117        //       trait bound modifiers are intentionally not included in `Token::can_begin_type` to
1118        //       avoid affecting stable macro matching behavior.
1119
1120        self.check_path()
1121            || self.check_lifetime()
1122            || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Bang,
    token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))
1123            || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Question,
    token_type: crate::parser::token_type::TokenType::Question,
}exp!(Question))
1124            || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Tilde,
    token_type: crate::parser::token_type::TokenType::Tilde,
}exp!(Tilde))
1125            || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::For,
    token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For))
1126            || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenParen,
    token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen))
1127            || self.can_begin_maybe_const_bound()
1128            || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))
1129            || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Async,
    token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async))
1130            || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Use,
    token_type: crate::parser::token_type::TokenType::KwUse,
}exp!(Use))
1131    }
1132
1133    fn can_begin_maybe_const_bound(&mut self) -> bool {
1134        self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenBracket,
    token_type: crate::parser::token_type::TokenType::OpenBracket,
}exp!(OpenBracket))
1135            && self.look_ahead(1, |t| t.is_keyword(kw::Const))
1136            && self.look_ahead(2, |t| *t == token::CloseBracket)
1137    }
1138
1139    /// Parse a bound.
1140    ///
1141    /// ```ebnf
1142    /// Bound = LifetimeBound | UseBound | TraitBound
1143    /// ```
1144    fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
1145        let leading_token = self.prev_token;
1146        let lo = self.token.span;
1147
1148        // We only admit parenthesized *trait* bounds. However, we want to gracefully recover from
1149        // other kinds of parenthesized bounds, so parse the opening parenthesis *here*.
1150        //
1151        // In the future we might want to lift this syntactic restriction and
1152        // introduce "`GenericBound::Paren(Box<GenericBound>)`".
1153        let parens = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenParen,
    token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };
1154
1155        if self.token.is_lifetime() {
1156            self.parse_lifetime_bound(lo, parens)
1157        } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Use,
    token_type: crate::parser::token_type::TokenType::KwUse,
}exp!(Use)) {
1158            self.parse_use_bound(lo, parens)
1159        } else {
1160            self.parse_trait_bound(lo, parens, &leading_token)
1161        }
1162    }
1163
1164    /// Parse a lifetime-bound aka outlives-bound.
1165    ///
1166    /// ```ebnf
1167    /// LifetimeBound = Lifetime
1168    /// ```
1169    fn parse_lifetime_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
1170        let lt = self.expect_lifetime();
1171
1172        if let ast::Parens::Yes = parens {
1173            self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1174            self.report_parenthesized_bound(lo, self.prev_token.span, "lifetime bounds");
1175        }
1176
1177        Ok(GenericBound::Outlives(lt))
1178    }
1179
1180    fn report_parenthesized_bound(&self, lo: Span, hi: Span, kind: &str) -> ErrorGuaranteed {
1181        let mut diag =
1182            self.dcx().struct_span_err(lo.to(hi), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} may not be parenthesized",
                kind))
    })format!("{kind} may not be parenthesized"));
1183        diag.multipart_suggestion(
1184            "remove the parentheses",
1185            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(lo, String::new()), (hi, String::new())]))vec![(lo, String::new()), (hi, String::new())],
1186            Applicability::MachineApplicable,
1187        );
1188        diag.emit_err()
1189    }
1190
1191    /// Emits an error if any trait bound modifiers were present.
1192    fn error_lt_bound_with_modifiers(
1193        &self,
1194        modifiers: TraitBoundModifiers,
1195        binder_span: Option<Span>,
1196    ) -> ErrorGuaranteed {
1197        let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;
1198
1199        match constness {
1200            BoundConstness::Never => {}
1201            BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
1202                return self.dcx().emit_err(diagnostics::ModifierLifetime {
1203                    span,
1204                    modifier: constness.as_str(),
1205                });
1206            }
1207        }
1208
1209        match polarity {
1210            BoundPolarity::Positive => {}
1211            BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
1212                return self
1213                    .dcx()
1214                    .emit_err(diagnostics::ModifierLifetime { span, modifier: polarity.as_str() });
1215            }
1216        }
1217
1218        match asyncness {
1219            BoundAsyncness::Normal => {}
1220            BoundAsyncness::Async(span) => {
1221                return self.dcx().emit_err(diagnostics::ModifierLifetime {
1222                    span,
1223                    modifier: asyncness.as_str(),
1224                });
1225            }
1226        }
1227
1228        if let Some(span) = binder_span {
1229            return self
1230                .dcx()
1231                .emit_err(diagnostics::ModifierLifetime { span, modifier: "for<...>" });
1232        }
1233
1234        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")));
}unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
1235    }
1236
1237    /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `[const] Trait`.
1238    ///
1239    /// If no modifiers are present, this does not consume any tokens.
1240    ///
1241    /// ```ebnf
1242    /// Constness = ("const" | "[" "const" "]")?
1243    /// Asyncness = "async"?
1244    /// Polarity = ("?" | "!")?
1245    /// ```
1246    ///
1247    /// See `parse_trait_bound` for more context.
1248    fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
1249        let modifier_lo = self.token.span;
1250        let constness = self.parse_bound_constness()?;
1251
1252        let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
1253            && self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Async,
    token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async))
1254        {
1255            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1256            BoundAsyncness::Async(self.prev_token.span)
1257        } else if self.may_recover()
1258            && self.token_uninterpolated_span().is_rust_2015()
1259            && self.is_kw_followed_by_ident(kw::Async)
1260        {
1261            self.bump(); // eat `async`
1262            self.dcx().emit_err(diagnostics::AsyncBoundModifierIn2015 {
1263                span: self.prev_token.span,
1264                help: HelpUseLatestEdition::new(),
1265            });
1266            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1267            BoundAsyncness::Async(self.prev_token.span)
1268        } else {
1269            BoundAsyncness::Normal
1270        };
1271        let modifier_hi = self.prev_token.span;
1272
1273        let polarity = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Question,
    token_type: crate::parser::token_type::TokenType::Question,
}exp!(Question)) {
1274            BoundPolarity::Maybe(self.prev_token.span)
1275        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Bang,
    token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
1276            self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
1277            BoundPolarity::Negative(self.prev_token.span)
1278        } else {
1279            BoundPolarity::Positive
1280        };
1281
1282        // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`.
1283        match polarity {
1284            BoundPolarity::Positive => {
1285                // All trait bound modifiers allowed to combine with positive polarity
1286            }
1287            BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
1288                match (asyncness, constness) {
1289                    (BoundAsyncness::Normal, BoundConstness::Never) => {
1290                        // Ok, no modifiers.
1291                    }
1292                    (_, _) => {
1293                        let constness = constness.as_str();
1294                        let asyncness = asyncness.as_str();
1295                        let glue =
1296                            if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
1297                        let modifiers_concatenated = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}{2}", constness, glue,
                asyncness))
    })format!("{constness}{glue}{asyncness}");
1298                        self.dcx().emit_err(diagnostics::PolarityAndModifiers {
1299                            polarity_span,
1300                            polarity: polarity.as_str(),
1301                            modifiers_span: modifier_lo.to(modifier_hi),
1302                            modifiers_concatenated,
1303                        });
1304                    }
1305                }
1306            }
1307        }
1308
1309        Ok(TraitBoundModifiers { constness, asyncness, polarity })
1310    }
1311
1312    pub fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> {
1313        // FIXME(const_trait_impl): remove `~const` parser support once bootstrap has the new syntax
1314        // in rustfmt
1315        Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Tilde,
    token_type: crate::parser::token_type::TokenType::Tilde,
}exp!(Tilde)) {
1316            let tilde = self.prev_token.span;
1317            self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1318            let span = tilde.to(self.prev_token.span);
1319            self.psess.gated_spans.gate(sym::const_trait_impl, span);
1320            BoundConstness::Maybe(span)
1321        } else if self.can_begin_maybe_const_bound() {
1322            let start = self.token.span;
1323            self.bump();
1324            self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)).unwrap();
1325            self.bump();
1326            let span = start.to(self.prev_token.span);
1327            self.psess.gated_spans.gate(sym::const_trait_impl, span);
1328            BoundConstness::Maybe(span)
1329        } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) {
1330            self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
1331            BoundConstness::Always(self.prev_token.span)
1332        } else {
1333            BoundConstness::Never
1334        })
1335    }
1336
1337    /// Parse a trait bound.
1338    ///
1339    /// ```ebnf
1340    /// TraitBound = BareTraitBound | "(" BareTraitBound ")"
1341    /// BareTraitBound =
1342    ///     (HigherRankedBinder Constness Asyncness | Polarity)
1343    ///     TypePath
1344    /// ```
1345    fn parse_trait_bound(
1346        &mut self,
1347        lo: Span,
1348        parens: ast::Parens,
1349        leading_token: &Token,
1350    ) -> PResult<'a, GenericBound> {
1351        let (mut bound_vars, binder_span) = self.parse_higher_ranked_binder()?;
1352
1353        let modifiers_lo = self.token.span;
1354        let modifiers = self.parse_trait_bound_modifiers()?;
1355        let modifiers_span = modifiers_lo.to(self.prev_token.span);
1356
1357        if let Some(binder_span) = binder_span {
1358            match modifiers.polarity {
1359                BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
1360                    self.dcx().emit_err(diagnostics::BinderAndPolarity {
1361                        binder_span,
1362                        polarity_span,
1363                        polarity: modifiers.polarity.as_str(),
1364                    });
1365                }
1366                BoundPolarity::Positive => {}
1367            }
1368        }
1369
1370        // Recover erroneous lifetime bound with modifiers or binder.
1371        // e.g. `T: for<'a> 'a` or `T: [const] 'a`.
1372        if self.token.is_lifetime() {
1373            let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
1374            return self.parse_lifetime_bound(lo, parens);
1375        }
1376
1377        if let (more_bound_vars, Some(binder_span)) = self.parse_higher_ranked_binder()? {
1378            bound_vars.extend(more_bound_vars);
1379            self.dcx().emit_err(diagnostics::BinderBeforeModifiers { binder_span, modifiers_span });
1380        }
1381
1382        let mut path = if self.token.is_keyword(kw::Fn)
1383            && self.look_ahead(1, |t| *t == TokenKind::OpenParen)
1384            && let Some(path) = self.recover_path_from_fn()
1385        {
1386            path
1387        } else if !self.token.is_path_start() && self.token.can_begin_type() {
1388            let ty = self.parse_ty_no_plus()?;
1389            // Instead of finding a path (a trait), we found a type.
1390            let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");
1391
1392            // If we can recover, try to extract a path from the type. Note
1393            // that we do not use the try operator when parsing the type because
1394            // if it fails then we get a parser error which we don't want (we're trying
1395            // to recover from errors, not make more).
1396            let path = if self.may_recover() {
1397                let (span, message, sugg, path, applicability) = match &ty.kind {
1398                    TyKind::Ptr(..) | TyKind::Ref(..)
1399                        if let TyKind::Path(_, path) = &ty.peel_refs().kind =>
1400                    {
1401                        (
1402                            ty.span.until(path.span),
1403                            "consider removing the indirection",
1404                            "",
1405                            path,
1406                            Applicability::MaybeIncorrect,
1407                        )
1408                    }
1409                    TyKind::ImplTrait(_, bounds)
1410                        if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
1411                    {
1412                        (
1413                            ty.span.until(tr.span),
1414                            "use the trait bounds directly",
1415                            "",
1416                            &tr.trait_ref.path,
1417                            Applicability::MachineApplicable,
1418                        )
1419                    }
1420                    _ => return Err(err),
1421                };
1422
1423                err.span_suggestion_verbose(span, message, sugg, applicability);
1424
1425                path.clone()
1426            } else {
1427                return Err(err);
1428            };
1429
1430            err.emit();
1431
1432            path
1433        } else {
1434            self.parse_path(PathStyle::Type)?
1435        };
1436
1437        if self.may_recover() && self.token == TokenKind::OpenParen {
1438            self.recover_fn_trait_with_lifetime_params(&mut path, &mut bound_vars)?;
1439        }
1440
1441        if let ast::Parens::Yes = parens {
1442            // Someone has written something like `&dyn (Trait + Other)`. The correct code
1443            // would be `&(dyn Trait + Other)`
1444            if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
1445                self.eat_plus();
1446                self.parse_generic_bounds()?;
1447                self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1448
1449                self.dcx().emit_err(diagnostics::IncorrectParensTraitBounds {
1450                    span: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [lo, self.prev_token.span]))vec![lo, self.prev_token.span],
1451                    sugg: diagnostics::IncorrectParensTraitBoundsSugg {
1452                        wrong_span: leading_token.span.shrink_to_hi().to(lo),
1453                        new_span: leading_token.span.shrink_to_lo(),
1454                    },
1455                });
1456            } else {
1457                self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1458            }
1459        }
1460
1461        let poly_trait =
1462            PolyTraitRef::new(bound_vars, path, modifiers, lo.to(self.prev_token.span), parens);
1463        Ok(GenericBound::Trait(poly_trait))
1464    }
1465
1466    // recovers a `Fn(..)` parenthesized-style path from `fn(..)`
1467    fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1468        let fn_token_span = self.token.span;
1469        self.bump();
1470        let args_lo = self.token.span;
1471        let snapshot = self.create_snapshot_for_diagnostic();
1472        let mode = FnParseMode {
1473            req_name: |_, _| false,
1474            context: FnContext::Free,
1475            req_body: false,
1476            allow_const_params: false,
1477        };
1478        match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1479            Ok(decl) => {
1480                self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1481                Some(ast::Path {
1482                    span: fn_token_span.to(self.prev_token.span),
1483                    segments: {
    let len = [()].len();
    let mut vec = ::thin_vec::ThinVec::with_capacity(len);
    vec.push(ast::PathSegment {
            ident: Ident::new(sym::Fn, fn_token_span),
            id: DUMMY_NODE_ID,
            args: Some(Box::new(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
                            span: args_lo.to(self.prev_token.span),
                            inputs: decl.inputs.iter().map(|a| a.clone()).collect(),
                            inputs_span: args_lo.until(decl.output.span()),
                            output: decl.output.clone(),
                        }))),
        });
    vec
}thin_vec![ast::PathSegment {
1484                        ident: Ident::new(sym::Fn, fn_token_span),
1485                        id: DUMMY_NODE_ID,
1486                        args: Some(Box::new(ast::GenericArgs::Parenthesized(
1487                            ast::ParenthesizedArgs {
1488                                span: args_lo.to(self.prev_token.span),
1489                                inputs: decl.inputs.iter().map(|a| a.clone()).collect(),
1490                                inputs_span: args_lo.until(decl.output.span()),
1491                                output: decl.output.clone(),
1492                            }
1493                        ))),
1494                    }],
1495                })
1496            }
1497            Err(diag) => {
1498                diag.cancel();
1499                self.restore_snapshot(snapshot);
1500                None
1501            }
1502        }
1503    }
1504
1505    /// Parse an optional higher-ranked binder.
1506    ///
1507    /// ```ebnf
1508    /// HigherRankedBinder = ("for" "<" GenericParams ">")?
1509    /// ```
1510    pub(super) fn parse_higher_ranked_binder(
1511        &mut self,
1512    ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
1513        if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::For,
    token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For)) {
1514            let lo = self.token.span;
1515            self.expect_lt()?;
1516            let params = self.parse_generic_params()?;
1517            self.expect_gt()?;
1518            // We rely on AST validation to rule out invalid cases: There must not be
1519            // type or const parameters, and parameters must not have bounds.
1520            Ok((params, Some(lo.to(self.prev_token.span))))
1521        } else {
1522            Ok((ThinVec::new(), None))
1523        }
1524    }
1525
1526    /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments
1527    /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already
1528    /// been eaten.
1529    fn recover_fn_trait_with_lifetime_params(
1530        &mut self,
1531        fn_path: &mut ast::Path,
1532        lifetime_defs: &mut ThinVec<GenericParam>,
1533    ) -> PResult<'a, ()> {
1534        let fn_path_segment = fn_path.segments.last_mut().unwrap();
1535        let generic_args = if let Some(p_args) = &fn_path_segment.args {
1536            *p_args.clone()
1537        } else {
1538            // Normally it wouldn't come here because the upstream should have parsed
1539            // generic parameters (otherwise it's impossible to call this function).
1540            return Ok(());
1541        };
1542        let lifetimes =
1543            if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1544                &generic_args
1545            {
1546                args.into_iter()
1547                    .filter_map(|arg| {
1548                        if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1549                            && let ast::GenericArg::Lifetime(lifetime) = generic_arg
1550                        {
1551                            Some(lifetime)
1552                        } else {
1553                            None
1554                        }
1555                    })
1556                    .collect()
1557            } else {
1558                Vec::new()
1559            };
1560        // Only try to recover if the trait has lifetime params.
1561        if lifetimes.is_empty() {
1562            return Ok(());
1563        }
1564
1565        let snapshot = if self.parsing_generics {
1566            // The snapshot is only relevant if we're parsing the generics of an `fn` to avoid
1567            // incorrect recovery.
1568            Some(self.create_snapshot_for_diagnostic())
1569        } else {
1570            None
1571        };
1572        // Parse `(T, U) -> R`.
1573        let inputs_lo = self.token.span;
1574        let mode = FnParseMode {
1575            req_name: |_, _| false,
1576            context: FnContext::Free,
1577            req_body: false,
1578            allow_const_params: false,
1579        };
1580        let inputs = match self.parse_fn_params(&mode) {
1581            Ok(params) => params,
1582            Err(err) => {
1583                if let Some(snapshot) = snapshot {
1584                    self.restore_snapshot(snapshot);
1585                    err.cancel();
1586                    return Ok(());
1587                } else {
1588                    return Err(err);
1589                }
1590            }
1591        };
1592        let inputs_span = inputs_lo.to(self.prev_token.span);
1593        let output = match self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)
1594        {
1595            Ok(output) => output,
1596            Err(err) => {
1597                if let Some(snapshot) = snapshot {
1598                    self.restore_snapshot(snapshot);
1599                    err.cancel();
1600                    return Ok(());
1601                } else {
1602                    return Err(err);
1603                }
1604            }
1605        };
1606        let args = ast::ParenthesizedArgs {
1607            span: fn_path_segment.span().to(self.prev_token.span),
1608            inputs,
1609            inputs_span,
1610            output,
1611        }
1612        .into();
1613
1614        if let Some(snapshot) = snapshot
1615            && ![token::Comma, token::Gt, token::Plus].contains(&self.token.kind)
1616        {
1617            // We would expect another bound or the end of type params by now. Most likely we've
1618            // encountered a `(` *not* representing `Trait()`, but rather the start of the `fn`'s
1619            // argument list where the generic param list wasn't properly closed.
1620            self.restore_snapshot(snapshot);
1621            return Ok(());
1622        }
1623
1624        *fn_path_segment = ast::PathSegment {
1625            ident: fn_path_segment.ident,
1626            args: Some(args),
1627            id: ast::DUMMY_NODE_ID,
1628        };
1629
1630        // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
1631        let mut generic_params = lifetimes
1632            .iter()
1633            .map(|lt| GenericParam {
1634                id: lt.id,
1635                ident: lt.ident,
1636                attrs: ast::AttrVec::new(),
1637                bounds: ThinVec::new(),
1638                is_placeholder: false,
1639                kind: ast::GenericParamKind::Lifetime,
1640                colon_span: None,
1641            })
1642            .collect::<ThinVec<GenericParam>>();
1643        lifetime_defs.append(&mut generic_params);
1644
1645        let generic_args_span = generic_args.span();
1646        let snippet = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("for<{0}> ",
                lifetimes.iter().map(|lt|
                                lt.ident.as_str()).intersperse(", ").collect::<String>()))
    })format!(
1647            "for<{}> ",
1648            lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1649        );
1650        let before_fn_path = fn_path.span.shrink_to_lo();
1651        self.dcx()
1652            .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
1653            .with_multipart_suggestion(
1654                "consider using a higher-ranked trait bound instead",
1655                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(generic_args_span, "".to_owned()), (before_fn_path, snippet)]))vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1656                Applicability::MaybeIncorrect,
1657            )
1658            .emit();
1659        Ok(())
1660    }
1661
1662    pub(super) fn check_lifetime(&mut self) -> bool {
1663        self.expected_token_types.insert(TokenType::Lifetime);
1664        self.token.is_lifetime()
1665    }
1666
1667    /// Parses a single lifetime `'a` or panics.
1668    pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1669        if let Some((ident, kind)) = self.token.lifetime() {
1670            if kind == IdentKind::Normal && ident.without_first_quote().is_reserved_lifetime() {
1671                self.dcx().emit_err(diagnostics::KeywordLifetime { span: ident.span });
1672            }
1673
1674            self.bump();
1675            Lifetime { ident, id: ast::DUMMY_NODE_ID }
1676        } else {
1677            self.dcx().span_bug(self.token.span, "not a lifetime")
1678        }
1679    }
1680
1681    pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> Box<Ty> {
1682        Box::new(Ty { kind, span, id: ast::DUMMY_NODE_ID })
1683    }
1684}