rustc_parse/parser/
ty.rs

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/// Signals whether parsing a type should allow `+`.
26///
27/// For example, let T be the type `impl Default + 'static`
28/// With `AllowPlus::Yes`, T will be parsed successfully
29/// With `AllowPlus::No`, parsing T will return a parse error
30#[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/// Signals whether parsing a type should recover `->`.
48///
49/// More specifically, when parsing a function like:
50/// ```compile_fail
51/// fn foo() => u8 { 0 }
52/// fn bar(): u8 { 0 }
53/// ```
54/// The compiler will try to recover interpreting `foo() => u8` as `foo() -> u8` when calling
55/// `parse_ty` with anything except `RecoverReturnSign::No`, and it will try to recover `bar(): u8`
56/// as `bar() -> u8` when passing `RecoverReturnSign::Yes` to `parse_ty`
57#[derive(Copy, Clone, PartialEq)]
58pub(super) enum RecoverReturnSign {
59    Yes,
60    OnlyFatArrow,
61    No,
62}
63
64impl RecoverReturnSign {
65    /// [RecoverReturnSign::Yes] allows for recovering `fn foo() => u8` and `fn foo(): u8`,
66    /// [RecoverReturnSign::OnlyFatArrow] allows for recovering only `fn foo() => u8` (recovering
67    /// colons can cause problems when parsing where clauses), and
68    /// [RecoverReturnSign::No] doesn't allow for any recovery of the return type arrow
69    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// Is `...` (`CVarArgs`) legal at this level of type parsing?
79#[derive(PartialEq)]
80enum AllowCVariadic {
81    Yes,
82    No,
83}
84
85/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
86/// `IDENT<<u8 as Trait>::AssocTy>`.
87///
88/// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
89/// that `IDENT` is not the ident of a fn trait.
90fn 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    // `Not`, `Tilde` & `Const` are deliberately not part of this list to
96    // contain the number of potential regressions esp. in MBE code.
97    // `Const` would regress `rfc-2632-const-trait-impl/mbe-dyn-const-2015.rs`.
98    // `Not` would regress `dyn!(...)` macro calls in Rust 2015.
99    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    /// Parses a type.
108    pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
109        // Make sure deeply nested types don't overflow the stack.
110        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    /// Parse a type suitable for a function or function pointer parameter.
137    /// The difference from `parse_ty` is that this version allows `...`
138    /// (`CVarArgs`) at the top level of the type.
139    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    /// Parses a type in restricted contexts where `+` is not permitted.
151    ///
152    /// Example 1: `&'a TYPE`
153    ///     `+` is prohibited to maintain operator priority (P(+) < P(&)).
154    /// Example 2: `value1 as TYPE + value2`
155    ///     `+` is prohibited to avoid interactions with expression grammar.
156    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    /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin
168    /// for better diagnostics involving `?`.
169    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    /// Parse a type without recovering `:` as `->` to avoid breaking code such
192    /// as `where fn() : for<'a>`.
193    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    /// Parses an optional return type `[ -> TY ]` in a function declaration.
205    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            // FIXME(Centril): Can we unconditionally `allow_plus`?
214            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            // Don't `eat` to prevent `=>` from being added as an expected token which isn't
225            // actually expected and could only confuse users
226            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            // Never type `!`
270            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            // Reference
277            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            // A type to be inferred `_`
283            TyKind::Infer
284        } else if self.check_fn_front_matter(false, Case::Sensitive) {
285            // Function pointer type
286            self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?
287        } else if self.check_keyword(exp!(For)) {
288            // Function pointer type or bound list (trait object type) starting with a poly-trait.
289            //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
290            //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
291            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                // Try to recover `for<'a> dyn Trait` or `for<'a> impl Trait`.
301                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                    // Take the parsed bare trait object and turn it either
326                    // into a `dyn` object or an `impl Trait`.
327                    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            // Qualified path
356            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                    // FIXME(c_variadic): Should we just allow `...` syntactically
367                    // anywhere in a type and use semantic restrictions instead?
368                    // NOTE: This may regress certain MBE calls if done incorrectly.
369                    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        // Try to recover from use of `+` with incorrect priority.
388        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    /// Parses either:
412    /// - `(TYPE)`, a parenthesized type.
413    /// - `(TYPE,)`, a tuple with a single field of type TYPE.
414    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                // `(TY_BOUND_NOPAREN) + BOUND + ...`.
427                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                // For `('a) + …`, we know that `'a` in type position already lead to an error being
435                // emitted. To reduce output, let's indirectly suppress E0178 (bad `+` in type) and
436                // other irrelevant consequential errors.
437                TyKind::TraitObject(bounds, TraitObjectSyntax::None)
438                    if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
439                {
440                    self.parse_remaining_bounds(bounds, true)
441                }
442                // `(TYPE)`
443                _ => 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        // A lifetime only begins a bare trait object type if it is followed by `+`!
452        if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
453            // In Rust 2021 and beyond, we assume that the user didn't intend to write a bare trait
454            // object type with a leading lifetime bound since that seems very unlikely given the
455            // fact that `dyn`-less trait objects are *semantically* invalid.
456            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    /// Parse the remainder of a bare trait object type given an already parsed list.
527    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(); // `+`, or `+=` gets split and `+` is discarded
534            bounds.append(&mut self.parse_generic_bounds()?);
535        }
536        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
537    }
538
539    /// Parses a raw pointer type: `*[const | mut] $type`.
540    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    /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
554    /// The opening `[` bracket is already eaten.
555    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                // Recover from `[LIT; EXPR]` and `[LIT]`
563                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                // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
574                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    /// Recover from malformed array type syntax.
588    ///
589    /// This method attempts to recover from cases like:
590    /// - `[u8, 5]` → suggests using `;`, return a Array type
591    /// - `[u8 5]` → suggests using `;`, return a Array type
592    /// Consider to add more cases in the future.
593    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 we cannot recover, return the error immediately.
602        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            // Consume common erroneous separators.
610            self.prev_token.span
611        } else {
612            self.token.span.shrink_to_lo()
613        };
614
615        // we first try to parse pattern like `[u8 5]`
616        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            // A lifetime is invalid here: it would be part of a bare trait bound, which requires
650            // it to be followed by a plus, but we disallow plus in the pointee type.
651            // So we can handle this case as an error here, and suggest `'a mut`.
652            // If there *is* a plus next though, handling the error later provides better suggestions
653            // (like adding parentheses)
654            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            // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
673            let span = and_span.to(self.look_ahead(1, |t| t.span));
674            self.dcx().emit_err(DynAfterMut { span });
675
676            // Recovery
677            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    /// Parses `pin` and `mut` annotations on references.
690    ///
691    /// It must be either `pin const` or `pin mut`.
692    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    // Parses the `typeof(EXPR)`.
715    // To avoid ambiguity, the type is surrounded by parentheses.
716    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    /// Parses a function pointer type (`TyKind::FnPtr`).
724    /// ```ignore (illustrative)
725    ///    [unsafe] [extern "ABI"] fn (S) -> T
726    /// //  ^~~~~^          ^~~~^     ^~^    ^
727    /// //    |               |        |     |
728    /// //    |               |        |   Return type
729    /// // Function Style    ABI  Parameter types
730    /// ```
731    /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
732    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    /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).
760    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    /// Parses an `impl B0 + ... + Bn` type.
802    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                    // parse pattern with "'a Sized" we're supposed to give suggestion like
807                    // "'a + Sized"
808                    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        // Always parse bounds greedily for better error recovery.
818        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    /// Is a `dyn B0 + ... + Bn` type allowed here?
858    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    /// Parses a `dyn B0 + ... + Bn` type.
868    ///
869    /// Note that this does *not* parse bare trait objects.
870    fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
871        self.bump(); // `dyn`
872
873        // We used to parse `*` for `dyn*` here.
874        let syntax = TraitObjectSyntax::Dyn;
875
876        // Always parse bounds greedily for better error recovery.
877        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    /// Parses a type starting with a path.
883    ///
884    /// This can be:
885    /// 1. a type macro, `mac!(...)`,
886    /// 2. a bare trait object, `B0 + ... + Bn`,
887    /// 3. or a path, `path::to::MyType`.
888    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        // Simple path
895        let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
896        if self.eat(exp!(Bang)) {
897            // Macro invocation in type position
898            Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
899        } else if allow_plus == AllowPlus::Yes && self.check_plus() {
900            // `Trait1 + Trait2 + 'a`
901            self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No)
902        } else {
903            // Just a type path.
904            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    /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
913    ///
914    /// See `parse_generic_bound` for the `BOUND` grammar.
915    fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
916        let mut bounds = Vec::new();
917
918        // In addition to looping while we find generic bounds:
919        // We continue even if we find a keyword. This is necessary for error recovery on,
920        // for example, `impl fn()`. The only keyword that can go after generic bounds is
921        // `where`, so stop if it's it.
922        // We also continue if we find types (not traits), again for error recovery.
923        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                // Account for `&dyn Trait + dyn Other`.
930                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    /// Can the current token begin a bound?
946    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    /// Parses a bound according to the grammar:
961    /// ```ebnf
962    /// BOUND = TY_BOUND | LT_BOUND
963    /// ```
964    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            // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of
973            // lifetimes and ident params (including SelfUpper). These are validated later
974            // for order, duplication, and whether they actually reference params.
975            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    /// Parses a lifetime ("outlives") bound, e.g. `'a`, according to:
986    /// ```ebnf
987    /// LT_BOUND = LIFETIME
988    /// ```
989    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            // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
998            // possibly introducing `GenericBound::Paren(P<GenericBound>)`?
999            self.recover_paren_lifetime(lo)?;
1000        }
1001        Ok(bound)
1002    }
1003
1004    /// Emits an error if any trait bound modifiers were present.
1005    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    /// Recover on `('lifetime)` with `(` already eaten.
1047    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    /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `[const] Trait`.
1057    ///
1058    /// If no modifiers are present, this does not consume any tokens.
1059    ///
1060    /// ```ebnf
1061    /// CONSTNESS = [["["] "const" ["]"]]
1062    /// ASYNCNESS = ["async"]
1063    /// POLARITY = ["?" | "!"]
1064    /// ```
1065    ///
1066    /// See `parse_generic_ty_bound` for the complete grammar of trait bound modifiers.
1067    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(); // eat `async`
1081            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        // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`.
1102        match polarity {
1103            BoundPolarity::Positive => {
1104                // All trait bound modifiers allowed to combine with positive polarity
1105            }
1106            BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
1107                match (asyncness, constness) {
1108                    (BoundAsyncness::Normal, BoundConstness::Never) => {
1109                        // Ok, no modifiers.
1110                    }
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        // FIXME(const_trait_impl): remove `~const` parser support once bootstrap has the new syntax
1133        // in rustfmt
1134        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    /// Parses a type bound according to:
1160    /// ```ebnf
1161    /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
1162    /// TY_BOUND_NOPAREN = [for<GENERIC_PARAMS> CONSTNESS ASYNCNESS | POLARITY] SIMPLE_PATH
1163    /// ```
1164    ///
1165    /// For example, this grammar accepts `for<'a: 'b> [const] ?m::Trait<'a>`.
1166    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        // Recover erroneous lifetime bound with modifiers or binder.
1192        // e.g. `T: for<'a> 'a` or `T: [const] 'a`.
1193        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            // Instead of finding a path (a trait), we found a type.
1211            let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");
1212
1213            // If we can recover, try to extract a path from the type. Note
1214            // that we do not use the try operator when parsing the type because
1215            // if it fails then we get a parser error which we don't want (we're trying
1216            // to recover from errors, not make more).
1217            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            // Someone has written something like `&dyn (Trait + Other)`. The correct code
1264            // would be `&(dyn Trait + Other)`
1265            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    // recovers a `Fn(..)` parenthesized-style path from `fn(..)`
1287    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    /// Optionally parses `for<$generic_params>`.
1319    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            // We rely on AST validation to rule out invalid cases: There must not be
1328            // type or const parameters, and parameters must not have bounds.
1329            Ok((params, Some(lo.to(self.prev_token.span))))
1330        } else {
1331            Ok((ThinVec::new(), None))
1332        }
1333    }
1334
1335    /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments
1336    /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already
1337    /// been eaten.
1338    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            // Normally it wouldn't come here because the upstream should have parsed
1348            // generic parameters (otherwise it's impossible to call this function).
1349            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        // Only try to recover if the trait has lifetime params.
1370        if lifetimes.is_empty() {
1371            return Ok(());
1372        }
1373
1374        // Parse `(T, U) -> R`.
1375        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        // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
1394        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    /// Parses a single lifetime `'a` or panics.
1431    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}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy