1use rustc_ast::ptr::P;
2use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token, TokenKind};
3use rustc_ast::util::case::Case;
4use rustc_ast::{
5    self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy,
6    GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
7    Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
8    TyKind, UnsafeBinderTy,
9};
10use rustc_data_structures::stack::ensure_sufficient_stack;
11use rustc_errors::{Applicability, Diag, PResult};
12use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
13use thin_vec::{ThinVec, thin_vec};
14
15use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
16use crate::errors::{
17    self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
18    FnPtrWithGenerics, FnPtrWithGenericsSugg, HelpUseLatestEdition, InvalidDynKeyword,
19    LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,
20    ReturnTypesUseThinArrow,
21};
22use crate::parser::item::FrontMatterParsingMode;
23use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
24
25#[derive(Copy, Clone, PartialEq)]
31pub(super) enum AllowPlus {
32    Yes,
33    No,
34}
35
36#[derive(PartialEq)]
37pub(super) enum RecoverQPath {
38    Yes,
39    No,
40}
41
42pub(super) enum RecoverQuestionMark {
43    Yes,
44    No,
45}
46
47#[derive(Copy, Clone, PartialEq)]
58pub(super) enum RecoverReturnSign {
59    Yes,
60    OnlyFatArrow,
61    No,
62}
63
64impl RecoverReturnSign {
65    fn can_recover(self, token: &TokenKind) -> bool {
70        match self {
71            Self::Yes => matches!(token, token::FatArrow | token::Colon),
72            Self::OnlyFatArrow => matches!(token, token::FatArrow),
73            Self::No => false,
74        }
75    }
76}
77
78#[derive(PartialEq)]
80enum AllowCVariadic {
81    Yes,
82    No,
83}
84
85fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
91    t == &token::PathSep || t == &token::Lt || t == &token::Shl
92}
93
94fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
95    t.is_path_start()
100        || t.is_lifetime()
101        || t == &TokenKind::Question
102        || t.is_keyword(kw::For)
103        || t == &TokenKind::OpenParen
104}
105
106impl<'a> Parser<'a> {
107    pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
109        ensure_sufficient_stack(|| {
111            self.parse_ty_common(
112                AllowPlus::Yes,
113                AllowCVariadic::No,
114                RecoverQPath::Yes,
115                RecoverReturnSign::Yes,
116                None,
117                RecoverQuestionMark::Yes,
118            )
119        })
120    }
121
122    pub(super) fn parse_ty_with_generics_recovery(
123        &mut self,
124        ty_params: &Generics,
125    ) -> PResult<'a, P<Ty>> {
126        self.parse_ty_common(
127            AllowPlus::Yes,
128            AllowCVariadic::No,
129            RecoverQPath::Yes,
130            RecoverReturnSign::Yes,
131            Some(ty_params),
132            RecoverQuestionMark::Yes,
133        )
134    }
135
136    pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
140        self.parse_ty_common(
141            AllowPlus::Yes,
142            AllowCVariadic::Yes,
143            RecoverQPath::Yes,
144            RecoverReturnSign::Yes,
145            None,
146            RecoverQuestionMark::Yes,
147        )
148    }
149
150    pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
157        self.parse_ty_common(
158            AllowPlus::No,
159            AllowCVariadic::No,
160            RecoverQPath::Yes,
161            RecoverReturnSign::Yes,
162            None,
163            RecoverQuestionMark::Yes,
164        )
165    }
166
167    pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
170        self.parse_ty_common(
171            AllowPlus::No,
172            AllowCVariadic::No,
173            RecoverQPath::Yes,
174            RecoverReturnSign::Yes,
175            None,
176            RecoverQuestionMark::No,
177        )
178    }
179
180    pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
181        self.parse_ty_common(
182            AllowPlus::Yes,
183            AllowCVariadic::No,
184            RecoverQPath::Yes,
185            RecoverReturnSign::Yes,
186            None,
187            RecoverQuestionMark::No,
188        )
189    }
190
191    pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
194        self.parse_ty_common(
195            AllowPlus::Yes,
196            AllowCVariadic::No,
197            RecoverQPath::Yes,
198            RecoverReturnSign::OnlyFatArrow,
199            None,
200            RecoverQuestionMark::Yes,
201        )
202    }
203
204    pub(super) fn parse_ret_ty(
206        &mut self,
207        allow_plus: AllowPlus,
208        recover_qpath: RecoverQPath,
209        recover_return_sign: RecoverReturnSign,
210    ) -> PResult<'a, FnRetTy> {
211        let lo = self.prev_token.span;
212        Ok(if self.eat(exp!(RArrow)) {
213            let ty = self.parse_ty_common(
215                allow_plus,
216                AllowCVariadic::No,
217                recover_qpath,
218                recover_return_sign,
219                None,
220                RecoverQuestionMark::Yes,
221            )?;
222            FnRetTy::Ty(ty)
223        } else if recover_return_sign.can_recover(&self.token.kind) {
224            self.bump();
227            self.dcx().emit_err(ReturnTypesUseThinArrow {
228                span: self.prev_token.span,
229                suggestion: lo.between(self.token.span),
230            });
231            let ty = self.parse_ty_common(
232                allow_plus,
233                AllowCVariadic::No,
234                recover_qpath,
235                recover_return_sign,
236                None,
237                RecoverQuestionMark::Yes,
238            )?;
239            FnRetTy::Ty(ty)
240        } else {
241            FnRetTy::Default(self.prev_token.span.shrink_to_hi())
242        })
243    }
244
245    fn parse_ty_common(
246        &mut self,
247        allow_plus: AllowPlus,
248        allow_c_variadic: AllowCVariadic,
249        recover_qpath: RecoverQPath,
250        recover_return_sign: RecoverReturnSign,
251        ty_generics: Option<&Generics>,
252        recover_question_mark: RecoverQuestionMark,
253    ) -> PResult<'a, P<Ty>> {
254        let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
255        maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
256
257        if let Some(ty) = self.eat_metavar_seq_with_matcher(
258            |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
259            |this| this.parse_ty_no_question_mark_recover(),
260        ) {
261            return Ok(ty);
262        }
263
264        let lo = self.token.span;
265        let mut impl_dyn_multi = false;
266        let kind = if self.check(exp!(OpenParen)) {
267            self.parse_ty_tuple_or_parens(lo, allow_plus)?
268        } else if self.eat(exp!(Bang)) {
269            TyKind::Never
271        } else if self.eat(exp!(Star)) {
272            self.parse_ty_ptr()?
273        } else if self.eat(exp!(OpenBracket)) {
274            self.parse_array_or_slice_ty()?
275        } else if self.check(exp!(And)) || self.check(exp!(AndAnd)) {
276            self.expect_and()?;
278            self.parse_borrowed_pointee()?
279        } else if self.eat_keyword_noexpect(kw::Typeof) {
280            self.parse_typeof_ty()?
281        } else if self.eat_keyword(exp!(Underscore)) {
282            TyKind::Infer
284        } else if self.check_fn_front_matter(false, Case::Sensitive) {
285            self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?
287        } else if self.check_keyword(exp!(For)) {
288            let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
292            if self.check_fn_front_matter(false, Case::Sensitive) {
293                self.parse_ty_fn_ptr(
294                    lo,
295                    lifetime_defs,
296                    Some(self.prev_token.span.shrink_to_lo()),
297                    recover_return_sign,
298                )?
299            } else {
300                if self.may_recover()
302                    && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))
303                {
304                    let kw = self.prev_token.ident().unwrap().0;
305                    let removal_span = kw.span.with_hi(self.token.span.lo());
306                    let path = self.parse_path(PathStyle::Type)?;
307                    let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
308                    let kind = self.parse_remaining_bounds_path(
309                        lifetime_defs,
310                        path,
311                        lo,
312                        parse_plus,
313                        ast::Parens::No,
314                    )?;
315                    let err = self.dcx().create_err(errors::TransposeDynOrImpl {
316                        span: kw.span,
317                        kw: kw.name.as_str(),
318                        sugg: errors::TransposeDynOrImplSugg {
319                            removal_span,
320                            insertion_span: lo.shrink_to_lo(),
321                            kw: kw.name.as_str(),
322                        },
323                    });
324
325                    let kind = match (kind, kw.name) {
328                        (TyKind::TraitObject(bounds, _), kw::Dyn) => {
329                            TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
330                        }
331                        (TyKind::TraitObject(bounds, _), kw::Impl) => {
332                            TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
333                        }
334                        _ => return Err(err),
335                    };
336                    err.emit();
337                    kind
338                } else {
339                    let path = self.parse_path(PathStyle::Type)?;
340                    let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
341                    self.parse_remaining_bounds_path(
342                        lifetime_defs,
343                        path,
344                        lo,
345                        parse_plus,
346                        ast::Parens::No,
347                    )?
348                }
349            }
350        } else if self.eat_keyword(exp!(Impl)) {
351            self.parse_impl_ty(&mut impl_dyn_multi)?
352        } else if self.is_explicit_dyn_type() {
353            self.parse_dyn_ty(&mut impl_dyn_multi)?
354        } else if self.eat_lt() {
355            let (qself, path) = self.parse_qpath(PathStyle::Type)?;
357            TyKind::Path(Some(qself), path)
358        } else if self.check_path() {
359            self.parse_path_start_ty(lo, allow_plus, ty_generics)?
360        } else if self.can_begin_bound() {
361            self.parse_bare_trait_object(lo, allow_plus)?
362        } else if self.eat(exp!(DotDotDot)) {
363            match allow_c_variadic {
364                AllowCVariadic::Yes => TyKind::CVarArgs,
365                AllowCVariadic::No => {
366                    let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });
370                    TyKind::Err(guar)
371                }
372            }
373        } else if self.check_keyword(exp!(Unsafe))
374            && self.look_ahead(1, |tok| tok.kind == token::Lt)
375        {
376            self.parse_unsafe_binder_ty()?
377        } else {
378            let msg = format!("expected type, found {}", super::token_descr(&self.token));
379            let mut err = self.dcx().struct_span_err(lo, msg);
380            err.span_label(lo, "expected type");
381            return Err(err);
382        };
383
384        let span = lo.to(self.prev_token.span);
385        let mut ty = self.mk_ty(span, kind);
386
387        match allow_plus {
389            AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
390            AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
391        }
392        if let RecoverQuestionMark::Yes = recover_question_mark {
393            ty = self.maybe_recover_from_question_mark(ty);
394        }
395        if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
396    }
397
398    fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
399        let lo = self.token.span;
400        assert!(self.eat_keyword(exp!(Unsafe)));
401        self.expect_lt()?;
402        let generic_params = self.parse_generic_params()?;
403        self.expect_gt()?;
404        let inner_ty = self.parse_ty()?;
405        let span = lo.to(self.prev_token.span);
406        self.psess.gated_spans.gate(sym::unsafe_binders, span);
407
408        Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty })))
409    }
410
411    fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
415        let mut trailing_plus = false;
416        let (ts, trailing) = self.parse_paren_comma_seq(|p| {
417            let ty = p.parse_ty()?;
418            trailing_plus = p.prev_token == TokenKind::Plus;
419            Ok(ty)
420        })?;
421
422        if ts.len() == 1 && matches!(trailing, Trailing::No) {
423            let ty = ts.into_iter().next().unwrap();
424            let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
425            match ty.kind {
426                TyKind::Path(None, path) if maybe_bounds => self.parse_remaining_bounds_path(
428                    ThinVec::new(),
429                    path,
430                    lo,
431                    true,
432                    ast::Parens::Yes,
433                ),
434                TyKind::TraitObject(bounds, TraitObjectSyntax::None)
438                    if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
439                {
440                    self.parse_remaining_bounds(bounds, true)
441                }
442                _ => Ok(TyKind::Paren(ty)),
444            }
445        } else {
446            Ok(TyKind::Tup(ts))
447        }
448    }
449
450    fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
451        if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
453            if self.psess.edition.at_least_rust_2021() {
457                let lt = self.expect_lifetime();
458                let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
459                err.span_label(lo, "expected type");
460                return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
461                    Ok(ref_ty) => ref_ty,
462                    Err(err) => TyKind::Err(err.emit()),
463                });
464            }
465
466            self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
467                span: lo,
468                suggestion: lo.shrink_to_hi(),
469            });
470        }
471        Ok(TyKind::TraitObject(
472            self.parse_generic_bounds_common(allow_plus)?,
473            TraitObjectSyntax::None,
474        ))
475    }
476
477    fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
478        &mut self,
479        lt: Lifetime,
480        lo: Span,
481        mut err: Diag<'cx>,
482    ) -> Result<TyKind, Diag<'cx>> {
483        if !self.may_recover() {
484            return Err(err);
485        }
486        let snapshot = self.create_snapshot_for_diagnostic();
487        let mutbl = self.parse_mutability();
488        match self.parse_ty_no_plus() {
489            Ok(ty) => {
490                err.span_suggestion_verbose(
491                    lo.shrink_to_lo(),
492                    "you might have meant to write a reference type here",
493                    "&",
494                    Applicability::MaybeIncorrect,
495                );
496                err.emit();
497                Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))
498            }
499            Err(diag) => {
500                diag.cancel();
501                self.restore_snapshot(snapshot);
502                Err(err)
503            }
504        }
505    }
506
507    fn parse_remaining_bounds_path(
508        &mut self,
509        generic_params: ThinVec<GenericParam>,
510        path: ast::Path,
511        lo: Span,
512        parse_plus: bool,
513        parens: ast::Parens,
514    ) -> PResult<'a, TyKind> {
515        let poly_trait_ref = PolyTraitRef::new(
516            generic_params,
517            path,
518            TraitBoundModifiers::NONE,
519            lo.to(self.prev_token.span),
520            parens,
521        );
522        let bounds = vec![GenericBound::Trait(poly_trait_ref)];
523        self.parse_remaining_bounds(bounds, parse_plus)
524    }
525
526    fn parse_remaining_bounds(
528        &mut self,
529        mut bounds: GenericBounds,
530        plus: bool,
531    ) -> PResult<'a, TyKind> {
532        if plus {
533            self.eat_plus(); bounds.append(&mut self.parse_generic_bounds()?);
535        }
536        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
537    }
538
539    fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
541        let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
542            let span = self.prev_token.span;
543            self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {
544                span,
545                after_asterisk: span.shrink_to_hi(),
546            });
547            Mutability::Not
548        });
549        let ty = self.parse_ty_no_plus()?;
550        Ok(TyKind::Ptr(MutTy { ty, mutbl }))
551    }
552
553    fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
556        let elt_ty = match self.parse_ty() {
557            Ok(ty) => ty,
558            Err(err)
559                if self.look_ahead(1, |t| *t == token::CloseBracket)
560                    | self.look_ahead(1, |t| *t == token::Semi) =>
561            {
562                self.bump();
564                let guar = err.emit();
565                self.mk_ty(self.prev_token.span, TyKind::Err(guar))
566            }
567            Err(err) => return Err(err),
568        };
569
570        let ty = if self.eat(exp!(Semi)) {
571            let mut length = self.parse_expr_anon_const()?;
572            if let Err(e) = self.expect(exp!(CloseBracket)) {
573                self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
575                self.expect(exp!(CloseBracket))?;
576            }
577            TyKind::Array(elt_ty, length)
578        } else if self.eat(exp!(CloseBracket)) {
579            TyKind::Slice(elt_ty)
580        } else {
581            self.maybe_recover_array_ty_without_semi(elt_ty)?
582        };
583
584        Ok(ty)
585    }
586
587    fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: P<Ty>) -> PResult<'a, TyKind> {
594        let span = self.token.span;
595        let token_descr = super::token_descr(&self.token);
596        let mut err =
597            self.dcx().struct_span_err(span, format!("expected `;` or `]`, found {}", token_descr));
598        err.span_label(span, "expected `;` or `]`");
599        err.note("you might have meant to write a slice or array type");
600
601        if !self.may_recover() {
603            return Err(err);
604        }
605
606        let snapshot = self.create_snapshot_for_diagnostic();
607
608        let suggestion_span = if self.eat(exp!(Comma)) || self.eat(exp!(Star)) {
609            self.prev_token.span
611        } else {
612            self.token.span.shrink_to_lo()
613        };
614
615        let length = match self.parse_expr_anon_const() {
617            Ok(length) => length,
618            Err(e) => {
619                e.cancel();
620                self.restore_snapshot(snapshot);
621                return Err(err);
622            }
623        };
624
625        if let Err(e) = self.expect(exp!(CloseBracket)) {
626            e.cancel();
627            self.restore_snapshot(snapshot);
628            return Err(err);
629        }
630
631        err.span_suggestion_verbose(
632            suggestion_span,
633            "you might have meant to use `;` as the separator",
634            ";",
635            Applicability::MaybeIncorrect,
636        );
637        err.emit();
638        Ok(TyKind::Array(elt_ty, length))
639    }
640
641    fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
642        let and_span = self.prev_token.span;
643        let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
644        let (pinned, mut mutbl) = match self.parse_pin_and_mut() {
645            Some(pin_mut) => pin_mut,
646            None => (Pinnedness::Not, self.parse_mutability()),
647        };
648        if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
649            if !self.look_ahead(1, |t| t.is_like_plus()) {
655                let lifetime_span = self.token.span;
656                let span = and_span.to(lifetime_span);
657
658                let (suggest_lifetime, snippet) =
659                    if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
660                        (Some(span), lifetime_src)
661                    } else {
662                        (None, String::new())
663                    };
664                self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
665
666                opt_lifetime = Some(self.expect_lifetime());
667            }
668        } else if self.token.is_keyword(kw::Dyn)
669            && mutbl == Mutability::Not
670            && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
671        {
672            let span = and_span.to(self.look_ahead(1, |t| t.span));
674            self.dcx().emit_err(DynAfterMut { span });
675
676            mutbl = Mutability::Mut;
678            let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
679            self.bump();
680            self.bump_with((dyn_tok, dyn_tok_sp));
681        }
682        let ty = self.parse_ty_no_plus()?;
683        Ok(match pinned {
684            Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
685            Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
686        })
687    }
688
689    pub(crate) fn parse_pin_and_mut(&mut self) -> Option<(Pinnedness, Mutability)> {
693        if self.token.is_ident_named(sym::pin) {
694            let result = self.look_ahead(1, |token| {
695                if token.is_keyword(kw::Const) {
696                    Some((Pinnedness::Pinned, Mutability::Not))
697                } else if token.is_keyword(kw::Mut) {
698                    Some((Pinnedness::Pinned, Mutability::Mut))
699                } else {
700                    None
701                }
702            });
703            if result.is_some() {
704                self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
705                self.bump();
706                self.bump();
707            }
708            result
709        } else {
710            None
711        }
712    }
713
714    fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
717        self.expect(exp!(OpenParen))?;
718        let expr = self.parse_expr_anon_const()?;
719        self.expect(exp!(CloseParen))?;
720        Ok(TyKind::Typeof(expr))
721    }
722
723    fn parse_ty_fn_ptr(
733        &mut self,
734        lo: Span,
735        mut params: ThinVec<GenericParam>,
736        param_insertion_point: Option<Span>,
737        recover_return_sign: RecoverReturnSign,
738    ) -> PResult<'a, TyKind> {
739        let inherited_vis = rustc_ast::Visibility {
740            span: rustc_span::DUMMY_SP,
741            kind: rustc_ast::VisibilityKind::Inherited,
742            tokens: None,
743        };
744        let span_start = self.token.span;
745        let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(
746            &inherited_vis,
747            Case::Sensitive,
748            FrontMatterParsingMode::FunctionPtrType,
749        )?;
750        if self.may_recover() && self.token == TokenKind::Lt {
751            self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
752        }
753        let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
754
755        let decl_span = span_start.to(self.prev_token.span);
756        Ok(TyKind::FnPtr(P(FnPtrTy { ext, safety, generic_params: params, decl, decl_span })))
757    }
758
759    fn recover_fn_ptr_with_generics(
761        &mut self,
762        lo: Span,
763        params: &mut ThinVec<GenericParam>,
764        param_insertion_point: Option<Span>,
765    ) -> PResult<'a, ()> {
766        let generics = self.parse_generics()?;
767        let arity = generics.params.len();
768
769        let mut lifetimes: ThinVec<_> = generics
770            .params
771            .into_iter()
772            .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
773            .collect();
774
775        let sugg = if !lifetimes.is_empty() {
776            let snippet =
777                lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
778
779            let (left, snippet) = if let Some(span) = param_insertion_point {
780                (span, if params.is_empty() { snippet } else { format!(", {snippet}") })
781            } else {
782                (lo.shrink_to_lo(), format!("for<{snippet}> "))
783            };
784
785            Some(FnPtrWithGenericsSugg {
786                left,
787                snippet,
788                right: generics.span,
789                arity,
790                for_param_list_exists: param_insertion_point.is_some(),
791            })
792        } else {
793            None
794        };
795
796        self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });
797        params.append(&mut lifetimes);
798        Ok(())
799    }
800
801    fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
803        if self.token.is_lifetime() {
804            self.look_ahead(1, |t| {
805                if let token::Ident(sym, _) = t.kind {
806                    self.dcx().emit_err(errors::MissingPlusBounds {
809                        span: self.token.span,
810                        hi: self.token.span.shrink_to_hi(),
811                        sym,
812                    });
813                }
814            })
815        }
816
817        let bounds = self.parse_generic_bounds()?;
819
820        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
821
822        Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
823    }
824
825    fn parse_precise_capturing_args(
826        &mut self,
827    ) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> {
828        let lo = self.token.span;
829        self.expect_lt()?;
830        let (args, _, _) = self.parse_seq_to_before_tokens(
831            &[exp!(Gt)],
832            &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
833            SeqSep::trailing_allowed(exp!(Comma)),
834            |self_| {
835                if self_.check_keyword(exp!(SelfUpper)) {
836                    self_.bump();
837                    Ok(PreciseCapturingArg::Arg(
838                        ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
839                        DUMMY_NODE_ID,
840                    ))
841                } else if self_.check_ident() {
842                    Ok(PreciseCapturingArg::Arg(
843                        ast::Path::from_ident(self_.parse_ident()?),
844                        DUMMY_NODE_ID,
845                    ))
846                } else if self_.check_lifetime() {
847                    Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
848                } else {
849                    self_.unexpected_any()
850                }
851            },
852        )?;
853        self.expect_gt()?;
854        Ok((args, lo.to(self.prev_token.span)))
855    }
856
857    fn is_explicit_dyn_type(&mut self) -> bool {
859        self.check_keyword(exp!(Dyn))
860            && (self.token_uninterpolated_span().at_least_rust_2018()
861                || self.look_ahead(1, |t| {
862                    (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::Star)
863                        && !can_continue_type_after_non_fn_ident(t)
864                }))
865    }
866
867    fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
871        self.bump(); let syntax = TraitObjectSyntax::Dyn;
875
876        let bounds = self.parse_generic_bounds()?;
878        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
879        Ok(TyKind::TraitObject(bounds, syntax))
880    }
881
882    fn parse_path_start_ty(
889        &mut self,
890        lo: Span,
891        allow_plus: AllowPlus,
892        ty_generics: Option<&Generics>,
893    ) -> PResult<'a, TyKind> {
894        let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
896        if self.eat(exp!(Bang)) {
897            Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
899        } else if allow_plus == AllowPlus::Yes && self.check_plus() {
900            self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No)
902        } else {
903            Ok(TyKind::Path(None, path))
905        }
906    }
907
908    pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
909        self.parse_generic_bounds_common(AllowPlus::Yes)
910    }
911
912    fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
916        let mut bounds = Vec::new();
917
918        while self.can_begin_bound()
924            || (self.may_recover()
925                && (self.token.can_begin_type()
926                    || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
927        {
928            if self.token.is_keyword(kw::Dyn) {
929                self.bump();
931                self.dcx().emit_err(InvalidDynKeyword {
932                    span: self.prev_token.span,
933                    suggestion: self.prev_token.span.until(self.token.span),
934                });
935            }
936            bounds.push(self.parse_generic_bound()?);
937            if allow_plus == AllowPlus::No || !self.eat_plus() {
938                break;
939            }
940        }
941
942        Ok(bounds)
943    }
944
945    fn can_begin_bound(&mut self) -> bool {
947        self.check_path()
948            || self.check_lifetime()
949            || self.check(exp!(Bang))
950            || self.check(exp!(Question))
951            || self.check(exp!(Tilde))
952            || self.check_keyword(exp!(For))
953            || self.check(exp!(OpenParen))
954            || self.check(exp!(OpenBracket))
955            || self.check_keyword(exp!(Const))
956            || self.check_keyword(exp!(Async))
957            || self.check_keyword(exp!(Use))
958    }
959
960    fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
965        let lo = self.token.span;
966        let leading_token = self.prev_token;
967        let parens = if self.eat(exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };
968
969        let bound = if self.token.is_lifetime() {
970            self.parse_generic_lt_bound(lo, parens)?
971        } else if self.eat_keyword(exp!(Use)) {
972            let use_span = self.prev_token.span;
976            let (args, args_span) = self.parse_precise_capturing_args()?;
977            GenericBound::Use(args, use_span.to(args_span))
978        } else {
979            self.parse_generic_ty_bound(lo, parens, &leading_token)?
980        };
981
982        Ok(bound)
983    }
984
985    fn parse_generic_lt_bound(
990        &mut self,
991        lo: Span,
992        parens: ast::Parens,
993    ) -> PResult<'a, GenericBound> {
994        let lt = self.expect_lifetime();
995        let bound = GenericBound::Outlives(lt);
996        if let ast::Parens::Yes = parens {
997            self.recover_paren_lifetime(lo)?;
1000        }
1001        Ok(bound)
1002    }
1003
1004    fn error_lt_bound_with_modifiers(
1006        &self,
1007        modifiers: TraitBoundModifiers,
1008        binder_span: Option<Span>,
1009    ) -> ErrorGuaranteed {
1010        let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;
1011
1012        match constness {
1013            BoundConstness::Never => {}
1014            BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
1015                return self
1016                    .dcx()
1017                    .emit_err(errors::ModifierLifetime { span, modifier: constness.as_str() });
1018            }
1019        }
1020
1021        match polarity {
1022            BoundPolarity::Positive => {}
1023            BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
1024                return self
1025                    .dcx()
1026                    .emit_err(errors::ModifierLifetime { span, modifier: polarity.as_str() });
1027            }
1028        }
1029
1030        match asyncness {
1031            BoundAsyncness::Normal => {}
1032            BoundAsyncness::Async(span) => {
1033                return self
1034                    .dcx()
1035                    .emit_err(errors::ModifierLifetime { span, modifier: asyncness.as_str() });
1036            }
1037        }
1038
1039        if let Some(span) = binder_span {
1040            return self.dcx().emit_err(errors::ModifierLifetime { span, modifier: "for<...>" });
1041        }
1042
1043        unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
1044    }
1045
1046    fn recover_paren_lifetime(&mut self, lo: Span) -> PResult<'a, ()> {
1048        self.expect(exp!(CloseParen))?;
1049        let span = lo.to(self.prev_token.span);
1050        let sugg = errors::RemoveParens { lo, hi: self.prev_token.span };
1051
1052        self.dcx().emit_err(errors::ParenthesizedLifetime { span, sugg });
1053        Ok(())
1054    }
1055
1056    fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
1068        let modifier_lo = self.token.span;
1069        let constness = self.parse_bound_constness()?;
1070
1071        let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
1072            && self.eat_keyword(exp!(Async))
1073        {
1074            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1075            BoundAsyncness::Async(self.prev_token.span)
1076        } else if self.may_recover()
1077            && self.token_uninterpolated_span().is_rust_2015()
1078            && self.is_kw_followed_by_ident(kw::Async)
1079        {
1080            self.bump(); self.dcx().emit_err(errors::AsyncBoundModifierIn2015 {
1082                span: self.prev_token.span,
1083                help: HelpUseLatestEdition::new(),
1084            });
1085            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1086            BoundAsyncness::Async(self.prev_token.span)
1087        } else {
1088            BoundAsyncness::Normal
1089        };
1090        let modifier_hi = self.prev_token.span;
1091
1092        let polarity = if self.eat(exp!(Question)) {
1093            BoundPolarity::Maybe(self.prev_token.span)
1094        } else if self.eat(exp!(Bang)) {
1095            self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
1096            BoundPolarity::Negative(self.prev_token.span)
1097        } else {
1098            BoundPolarity::Positive
1099        };
1100
1101        match polarity {
1103            BoundPolarity::Positive => {
1104                }
1106            BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
1107                match (asyncness, constness) {
1108                    (BoundAsyncness::Normal, BoundConstness::Never) => {
1109                        }
1111                    (_, _) => {
1112                        let constness = constness.as_str();
1113                        let asyncness = asyncness.as_str();
1114                        let glue =
1115                            if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
1116                        let modifiers_concatenated = format!("{constness}{glue}{asyncness}");
1117                        self.dcx().emit_err(errors::PolarityAndModifiers {
1118                            polarity_span,
1119                            polarity: polarity.as_str(),
1120                            modifiers_span: modifier_lo.to(modifier_hi),
1121                            modifiers_concatenated,
1122                        });
1123                    }
1124                }
1125            }
1126        }
1127
1128        Ok(TraitBoundModifiers { constness, asyncness, polarity })
1129    }
1130
1131    pub fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> {
1132        Ok(if self.eat(exp!(Tilde)) {
1135            let tilde = self.prev_token.span;
1136            self.expect_keyword(exp!(Const))?;
1137            let span = tilde.to(self.prev_token.span);
1138            self.psess.gated_spans.gate(sym::const_trait_impl, span);
1139            BoundConstness::Maybe(span)
1140        } else if self.check(exp!(OpenBracket))
1141            && self.look_ahead(1, |t| t.is_keyword(kw::Const))
1142            && self.look_ahead(2, |t| *t == token::CloseBracket)
1143        {
1144            let start = self.token.span;
1145            self.bump();
1146            self.expect_keyword(exp!(Const)).unwrap();
1147            self.bump();
1148            let span = start.to(self.prev_token.span);
1149            self.psess.gated_spans.gate(sym::const_trait_impl, span);
1150            BoundConstness::Maybe(span)
1151        } else if self.eat_keyword(exp!(Const)) {
1152            self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
1153            BoundConstness::Always(self.prev_token.span)
1154        } else {
1155            BoundConstness::Never
1156        })
1157    }
1158
1159    fn parse_generic_ty_bound(
1167        &mut self,
1168        lo: Span,
1169        parens: ast::Parens,
1170        leading_token: &Token,
1171    ) -> PResult<'a, GenericBound> {
1172        let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?;
1173
1174        let modifiers_lo = self.token.span;
1175        let modifiers = self.parse_trait_bound_modifiers()?;
1176        let modifiers_span = modifiers_lo.to(self.prev_token.span);
1177
1178        if let Some(binder_span) = binder_span {
1179            match modifiers.polarity {
1180                BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
1181                    self.dcx().emit_err(errors::BinderAndPolarity {
1182                        binder_span,
1183                        polarity_span,
1184                        polarity: modifiers.polarity.as_str(),
1185                    });
1186                }
1187                BoundPolarity::Positive => {}
1188            }
1189        }
1190
1191        if self.token.is_lifetime() {
1194            let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
1195            return self.parse_generic_lt_bound(lo, parens);
1196        }
1197
1198        if let (more_lifetime_defs, Some(binder_span)) = self.parse_late_bound_lifetime_defs()? {
1199            lifetime_defs.extend(more_lifetime_defs);
1200            self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span });
1201        }
1202
1203        let mut path = if self.token.is_keyword(kw::Fn)
1204            && self.look_ahead(1, |t| *t == TokenKind::OpenParen)
1205            && let Some(path) = self.recover_path_from_fn()
1206        {
1207            path
1208        } else if !self.token.is_path_start() && self.token.can_begin_type() {
1209            let ty = self.parse_ty_no_plus()?;
1210            let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");
1212
1213            let path = if self.may_recover() {
1218                let (span, message, sugg, path, applicability) = match &ty.kind {
1219                    TyKind::Ptr(..) | TyKind::Ref(..)
1220                        if let TyKind::Path(_, path) = &ty.peel_refs().kind =>
1221                    {
1222                        (
1223                            ty.span.until(path.span),
1224                            "consider removing the indirection",
1225                            "",
1226                            path,
1227                            Applicability::MaybeIncorrect,
1228                        )
1229                    }
1230                    TyKind::ImplTrait(_, bounds)
1231                        if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
1232                    {
1233                        (
1234                            ty.span.until(tr.span),
1235                            "use the trait bounds directly",
1236                            "",
1237                            &tr.trait_ref.path,
1238                            Applicability::MachineApplicable,
1239                        )
1240                    }
1241                    _ => return Err(err),
1242                };
1243
1244                err.span_suggestion_verbose(span, message, sugg, applicability);
1245
1246                path.clone()
1247            } else {
1248                return Err(err);
1249            };
1250
1251            err.emit();
1252
1253            path
1254        } else {
1255            self.parse_path(PathStyle::Type)?
1256        };
1257
1258        if self.may_recover() && self.token == TokenKind::OpenParen {
1259            self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?;
1260        }
1261
1262        if let ast::Parens::Yes = parens {
1263            if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
1266                let bounds = vec![];
1267                self.parse_remaining_bounds(bounds, true)?;
1268                self.expect(exp!(CloseParen))?;
1269                self.dcx().emit_err(errors::IncorrectParensTraitBounds {
1270                    span: vec![lo, self.prev_token.span],
1271                    sugg: errors::IncorrectParensTraitBoundsSugg {
1272                        wrong_span: leading_token.span.shrink_to_hi().to(lo),
1273                        new_span: leading_token.span.shrink_to_lo(),
1274                    },
1275                });
1276            } else {
1277                self.expect(exp!(CloseParen))?;
1278            }
1279        }
1280
1281        let poly_trait =
1282            PolyTraitRef::new(lifetime_defs, path, modifiers, lo.to(self.prev_token.span), parens);
1283        Ok(GenericBound::Trait(poly_trait))
1284    }
1285
1286    fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1288        let fn_token_span = self.token.span;
1289        self.bump();
1290        let args_lo = self.token.span;
1291        let snapshot = self.create_snapshot_for_diagnostic();
1292        match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1293            Ok(decl) => {
1294                self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1295                Some(ast::Path {
1296                    span: fn_token_span.to(self.prev_token.span),
1297                    segments: thin_vec![ast::PathSegment {
1298                        ident: Ident::new(sym::Fn, fn_token_span),
1299                        id: DUMMY_NODE_ID,
1300                        args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
1301                            span: args_lo.to(self.prev_token.span),
1302                            inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
1303                            inputs_span: args_lo.until(decl.output.span()),
1304                            output: decl.output.clone(),
1305                        }))),
1306                    }],
1307                    tokens: None,
1308                })
1309            }
1310            Err(diag) => {
1311                diag.cancel();
1312                self.restore_snapshot(snapshot);
1313                None
1314            }
1315        }
1316    }
1317
1318    pub(super) fn parse_late_bound_lifetime_defs(
1320        &mut self,
1321    ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
1322        if self.eat_keyword(exp!(For)) {
1323            let lo = self.token.span;
1324            self.expect_lt()?;
1325            let params = self.parse_generic_params()?;
1326            self.expect_gt()?;
1327            Ok((params, Some(lo.to(self.prev_token.span))))
1330        } else {
1331            Ok((ThinVec::new(), None))
1332        }
1333    }
1334
1335    fn recover_fn_trait_with_lifetime_params(
1339        &mut self,
1340        fn_path: &mut ast::Path,
1341        lifetime_defs: &mut ThinVec<GenericParam>,
1342    ) -> PResult<'a, ()> {
1343        let fn_path_segment = fn_path.segments.last_mut().unwrap();
1344        let generic_args = if let Some(p_args) = &fn_path_segment.args {
1345            *p_args.clone()
1346        } else {
1347            return Ok(());
1350        };
1351        let lifetimes =
1352            if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1353                &generic_args
1354            {
1355                args.into_iter()
1356                    .filter_map(|arg| {
1357                        if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1358                            && let ast::GenericArg::Lifetime(lifetime) = generic_arg
1359                        {
1360                            Some(lifetime)
1361                        } else {
1362                            None
1363                        }
1364                    })
1365                    .collect()
1366            } else {
1367                Vec::new()
1368            };
1369        if lifetimes.is_empty() {
1371            return Ok(());
1372        }
1373
1374        let inputs_lo = self.token.span;
1376        let inputs: ThinVec<_> =
1377            self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
1378        let inputs_span = inputs_lo.to(self.prev_token.span);
1379        let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
1380        let args = ast::ParenthesizedArgs {
1381            span: fn_path_segment.span().to(self.prev_token.span),
1382            inputs,
1383            inputs_span,
1384            output,
1385        }
1386        .into();
1387        *fn_path_segment = ast::PathSegment {
1388            ident: fn_path_segment.ident,
1389            args: Some(args),
1390            id: ast::DUMMY_NODE_ID,
1391        };
1392
1393        let mut generic_params = lifetimes
1395            .iter()
1396            .map(|lt| GenericParam {
1397                id: lt.id,
1398                ident: lt.ident,
1399                attrs: ast::AttrVec::new(),
1400                bounds: Vec::new(),
1401                is_placeholder: false,
1402                kind: ast::GenericParamKind::Lifetime,
1403                colon_span: None,
1404            })
1405            .collect::<ThinVec<GenericParam>>();
1406        lifetime_defs.append(&mut generic_params);
1407
1408        let generic_args_span = generic_args.span();
1409        let snippet = format!(
1410            "for<{}> ",
1411            lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1412        );
1413        let before_fn_path = fn_path.span.shrink_to_lo();
1414        self.dcx()
1415            .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
1416            .with_multipart_suggestion(
1417                "consider using a higher-ranked trait bound instead",
1418                vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1419                Applicability::MaybeIncorrect,
1420            )
1421            .emit();
1422        Ok(())
1423    }
1424
1425    pub(super) fn check_lifetime(&mut self) -> bool {
1426        self.expected_token_types.insert(TokenType::Lifetime);
1427        self.token.is_lifetime()
1428    }
1429
1430    pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1432        if let Some((ident, is_raw)) = self.token.lifetime() {
1433            if matches!(is_raw, IdentIsRaw::No)
1434                && ident.without_first_quote().is_reserved()
1435                && ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name)
1436            {
1437                self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
1438            }
1439
1440            self.bump();
1441            Lifetime { ident, id: ast::DUMMY_NODE_ID }
1442        } else {
1443            self.dcx().span_bug(self.token.span, "not a lifetime")
1444        }
1445    }
1446
1447    pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
1448        P(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
1449    }
1450}