1 use super::{Parser, PathStyle, TokenType};
4 DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
5 FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
6 InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
7 NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType,
8 ReturnTypesUseThinArrow,
10 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
12 use ast::DUMMY_NODE_ID;
13 use rustc_ast::ptr::P;
14 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
15 use rustc_ast::util::case::Case;
17 self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
18 MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
20 use rustc_ast_pretty::pprust;
21 use rustc_errors::{Applicability, PResult};
22 use rustc_span::source_map::Span;
23 use rustc_span::symbol::{kw, sym, Ident};
24 use rustc_span::Symbol;
25 use thin_vec::thin_vec;
27 /// Any `?` or `~const` modifiers that appear at the start of a bound.
28 struct BoundModifiers {
33 maybe_const: Option<Span>,
37 fn to_trait_bound_modifier(&self) -> TraitBoundModifier {
38 match (self.maybe, self.maybe_const) {
39 (None, None) => TraitBoundModifier::None,
40 (Some(_), None) => TraitBoundModifier::Maybe,
41 (None, Some(_)) => TraitBoundModifier::MaybeConst,
42 (Some(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe,
47 #[derive(Copy, Clone, PartialEq)]
48 pub(super) enum AllowPlus {
53 #[derive(PartialEq, Clone, Copy)]
54 pub(super) enum RecoverQPath {
59 #[derive(PartialEq, Clone, Copy)]
60 pub(super) enum RecoverQuestionMark {
65 #[derive(PartialEq, Clone, Copy)]
66 pub(super) enum RecoverAnonEnum {
71 /// Signals whether parsing a type should recover `->`.
73 /// More specifically, when parsing a function like:
75 /// fn foo() => u8 { 0 }
76 /// fn bar(): u8 { 0 }
78 /// The compiler will try to recover interpreting `foo() => u8` as `foo() -> u8` when calling
79 /// `parse_ty` with anything except `RecoverReturnSign::No`, and it will try to recover `bar(): u8`
80 /// as `bar() -> u8` when passing `RecoverReturnSign::Yes` to `parse_ty`
81 #[derive(Copy, Clone, PartialEq)]
82 pub(super) enum RecoverReturnSign {
88 impl RecoverReturnSign {
89 /// [RecoverReturnSign::Yes] allows for recovering `fn foo() => u8` and `fn foo(): u8`,
90 /// [RecoverReturnSign::OnlyFatArrow] allows for recovering only `fn foo() => u8` (recovering
91 /// colons can cause problems when parsing where clauses), and
92 /// [RecoverReturnSign::No] doesn't allow for any recovery of the return type arrow
93 fn can_recover(self, token: &TokenKind) -> bool {
95 Self::Yes => matches!(token, token::FatArrow | token::Colon),
96 Self::OnlyFatArrow => matches!(token, token::FatArrow),
102 // Is `...` (`CVarArgs`) legal at this level of type parsing?
103 #[derive(PartialEq, Clone, Copy)]
104 enum AllowCVariadic {
109 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
110 /// `IDENT<<u8 as Trait>::AssocTy>`.
112 /// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
113 /// that `IDENT` is not the ident of a fn trait.
114 fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
115 t == &token::ModSep || t == &token::Lt || t == &token::BinOp(token::Shl)
118 impl<'a> Parser<'a> {
120 pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
121 self.parse_ty_common(
125 RecoverReturnSign::Yes,
127 RecoverQuestionMark::Yes,
132 pub(super) fn parse_ty_with_generics_recovery(
134 ty_params: &Generics,
135 ) -> PResult<'a, P<Ty>> {
136 self.parse_ty_common(
140 RecoverReturnSign::Yes,
142 RecoverQuestionMark::Yes,
147 /// Parse a type suitable for a function or function pointer parameter.
148 /// The difference from `parse_ty` is that this version allows `...`
149 /// (`CVarArgs`) at the top level of the type.
150 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
151 self.parse_ty_common(
155 RecoverReturnSign::Yes,
157 RecoverQuestionMark::Yes,
158 RecoverAnonEnum::Yes,
162 /// Parses a type in restricted contexts where `+` is not permitted.
164 /// Example 1: `&'a TYPE`
165 /// `+` is prohibited to maintain operator priority (P(+) < P(&)).
166 /// Example 2: `value1 as TYPE + value2`
167 /// `+` is prohibited to avoid interactions with expression grammar.
168 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
169 self.parse_ty_common(
173 RecoverReturnSign::Yes,
175 RecoverQuestionMark::Yes,
180 /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin
181 /// for better diagnostics involving `?`.
182 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
183 self.parse_ty_common(
187 RecoverReturnSign::Yes,
189 RecoverQuestionMark::No,
194 pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
195 self.parse_ty_common(
199 RecoverReturnSign::Yes,
201 RecoverQuestionMark::No,
206 /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
207 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
208 self.parse_ty_common(
212 RecoverReturnSign::OnlyFatArrow,
214 RecoverQuestionMark::Yes,
219 /// Parses an optional return type `[ -> TY ]` in a function declaration.
220 pub(super) fn parse_ret_ty(
222 allow_plus: AllowPlus,
223 recover_qpath: RecoverQPath,
224 recover_return_sign: RecoverReturnSign,
225 ) -> PResult<'a, FnRetTy> {
226 Ok(if self.eat(&token::RArrow) {
227 // FIXME(Centril): Can we unconditionally `allow_plus`?
228 let ty = self.parse_ty_common(
234 RecoverQuestionMark::Yes,
235 RecoverAnonEnum::Yes,
238 } else if recover_return_sign.can_recover(&self.token.kind) {
239 // Don't `eat` to prevent `=>` from being added as an expected token which isn't
240 // actually expected and could only confuse users
242 self.sess.emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span });
243 let ty = self.parse_ty_common(
249 RecoverQuestionMark::Yes,
250 RecoverAnonEnum::Yes,
254 FnRetTy::Default(self.token.span.shrink_to_lo())
260 allow_plus: AllowPlus,
261 allow_c_variadic: AllowCVariadic,
262 recover_qpath: RecoverQPath,
263 recover_return_sign: RecoverReturnSign,
264 ty_generics: Option<&Generics>,
265 recover_question_mark: RecoverQuestionMark,
266 recover_anon_enum: RecoverAnonEnum,
267 ) -> PResult<'a, P<Ty>> {
268 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
269 maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
270 maybe_whole!(self, NtTy, |x| x);
272 let lo = self.token.span;
273 let mut impl_dyn_multi = false;
274 let kind = if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
275 self.parse_ty_tuple_or_parens(lo, allow_plus)?
276 } else if self.eat(&token::Not) {
279 } else if self.eat(&token::BinOp(token::Star)) {
281 } else if self.eat(&token::OpenDelim(Delimiter::Bracket)) {
282 self.parse_array_or_slice_ty()?
283 } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) {
286 self.parse_borrowed_pointee()?
287 } else if self.eat_keyword_noexpect(kw::Typeof) {
288 self.parse_typeof_ty()?
289 } else if self.eat_keyword(kw::Underscore) {
290 // A type to be inferred `_`
292 } else if self.check_fn_front_matter(false, Case::Sensitive) {
293 // Function pointer type
294 self.parse_ty_bare_fn(lo, Vec::new(), None, recover_return_sign)?
295 } else if self.check_keyword(kw::For) {
296 // Function pointer type or bound list (trait object type) starting with a poly-trait.
297 // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
298 // `for<'lt> Trait1<'lt> + Trait2 + 'a`
299 let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
300 if self.check_fn_front_matter(false, Case::Sensitive) {
301 self.parse_ty_bare_fn(
304 Some(self.prev_token.span.shrink_to_lo()),
308 let path = self.parse_path(PathStyle::Type)?;
309 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
310 self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
312 } else if self.eat_keyword(kw::Impl) {
313 self.parse_impl_ty(&mut impl_dyn_multi)?
314 } else if self.is_explicit_dyn_type() {
315 self.parse_dyn_ty(&mut impl_dyn_multi)?
316 } else if self.eat_lt() {
318 let (qself, path) = self.parse_qpath(PathStyle::Type)?;
319 TyKind::Path(Some(qself), path)
320 } else if self.check_path() {
321 self.parse_path_start_ty(lo, allow_plus, ty_generics)?
322 } else if self.can_begin_bound() {
323 self.parse_bare_trait_object(lo, allow_plus)?
324 } else if self.eat(&token::DotDotDot) {
325 match allow_c_variadic {
326 AllowCVariadic::Yes => TyKind::CVarArgs,
327 AllowCVariadic::No => {
328 // FIXME(Centril): Should we just allow `...` syntactically
329 // anywhere in a type and use semantic restrictions instead?
330 self.sess.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
335 let msg = format!("expected type, found {}", super::token_descr(&self.token));
336 let mut err = self.struct_span_err(self.token.span, &msg);
337 err.span_label(self.token.span, "expected type");
338 self.maybe_annotate_with_ascription(&mut err, true);
342 let span = lo.to(self.prev_token.span);
343 let mut ty = self.mk_ty(span, kind);
345 // Try to recover from use of `+` with incorrect priority.
347 AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
348 AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
350 if RecoverQuestionMark::Yes == recover_question_mark {
351 ty = self.maybe_recover_from_question_mark(ty);
353 if recover_anon_enum == RecoverAnonEnum::Yes
354 && self.check_noexpect(&token::BinOp(token::Or))
355 && self.look_ahead(1, |t| t.can_begin_type())
357 let mut pipes = vec![self.token.span];
358 let mut types = vec![ty];
360 if !self.eat(&token::BinOp(token::Or)) {
363 pipes.push(self.prev_token.span);
364 types.push(self.parse_ty_common(
370 recover_question_mark,
374 let mut err = self.struct_span_err(pipes, "anonymous enums are not supported");
376 err.span_label(ty.span, "");
379 "create a named `enum` and use it here instead:\nenum Name {{\n{}\n}}",
383 .map(|(i, t)| format!(
385 i + 1, // Lets not confuse people with zero-indexing :)
386 pprust::to_string(|s| s.print_type(&t)),
392 return Ok(self.mk_ty(lo.to(self.prev_token.span), TyKind::Err));
394 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
398 /// - `(TYPE)`, a parenthesized type.
399 /// - `(TYPE,)`, a tuple with a single field of type TYPE.
400 fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
401 let mut trailing_plus = false;
402 let (ts, trailing) = self.parse_paren_comma_seq(|p| {
403 let ty = p.parse_ty()?;
404 trailing_plus = p.prev_token.kind == TokenKind::BinOp(token::Plus);
408 if ts.len() == 1 && !trailing {
409 let ty = ts.into_iter().next().unwrap().into_inner();
410 let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
412 // `(TY_BOUND_NOPAREN) + BOUND + ...`.
413 TyKind::Path(None, path) if maybe_bounds => {
414 self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
416 TyKind::TraitObject(bounds, TraitObjectSyntax::None)
417 if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
419 self.parse_remaining_bounds(bounds, true)
422 _ => Ok(TyKind::Paren(P(ty))),
429 fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
430 let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
431 let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
433 self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
435 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
438 fn parse_remaining_bounds_path(
440 generic_params: Vec<GenericParam>,
444 ) -> PResult<'a, TyKind> {
445 let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span));
446 let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
447 self.parse_remaining_bounds(bounds, parse_plus)
450 /// Parse the remainder of a bare trait object type given an already parsed list.
451 fn parse_remaining_bounds(
453 mut bounds: GenericBounds,
455 ) -> PResult<'a, TyKind> {
457 self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
458 bounds.append(&mut self.parse_generic_bounds(Some(self.prev_token.span))?);
460 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
463 /// Parses a raw pointer type: `*[const | mut] $type`.
464 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
465 let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
466 let span = self.prev_token.span;
467 self.sess.emit_err(ExpectedMutOrConstInRawPointerType {
469 after_asterisk: span.shrink_to_hi(),
473 let ty = self.parse_ty_no_plus()?;
474 Ok(TyKind::Ptr(MutTy { ty, mutbl }))
477 /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
478 /// The opening `[` bracket is already eaten.
479 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
480 let elt_ty = match self.parse_ty() {
483 if self.look_ahead(1, |t| t.kind == token::CloseDelim(Delimiter::Bracket))
484 | self.look_ahead(1, |t| t.kind == token::Semi) =>
486 // Recover from `[LIT; EXPR]` and `[LIT]`
489 self.mk_ty(self.prev_token.span, TyKind::Err)
491 Err(err) => return Err(err),
494 let ty = if self.eat(&token::Semi) {
495 let mut length = self.parse_anon_const_expr()?;
496 if let Err(e) = self.expect(&token::CloseDelim(Delimiter::Bracket)) {
497 // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
498 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
499 self.expect(&token::CloseDelim(Delimiter::Bracket))?;
501 TyKind::Array(elt_ty, length)
503 self.expect(&token::CloseDelim(Delimiter::Bracket))?;
504 TyKind::Slice(elt_ty)
510 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
511 let and_span = self.prev_token.span;
512 let mut opt_lifetime =
513 if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
514 let mut mutbl = self.parse_mutability();
515 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
516 // A lifetime is invalid here: it would be part of a bare trait bound, which requires
517 // it to be followed by a plus, but we disallow plus in the pointee type.
518 // So we can handle this case as an error here, and suggest `'a mut`.
519 // If there *is* a plus next though, handling the error later provides better suggestions
520 // (like adding parentheses)
521 if !self.look_ahead(1, |t| t.is_like_plus()) {
522 let lifetime_span = self.token.span;
523 let span = and_span.to(lifetime_span);
525 let (suggest_lifetime, snippet) =
526 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
527 (Some(span), lifetime_src)
529 (None, String::new())
531 self.sess.emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
533 opt_lifetime = Some(self.expect_lifetime());
535 } else if self.token.is_keyword(kw::Dyn)
536 && mutbl == Mutability::Not
537 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
539 // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
540 let span = and_span.to(self.look_ahead(1, |t| t.span));
541 self.sess.emit_err(DynAfterMut { span });
544 mutbl = Mutability::Mut;
545 let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing);
547 self.bump_with((dyn_tok, dyn_tok_sp));
549 let ty = self.parse_ty_no_plus()?;
550 Ok(TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }))
553 // Parses the `typeof(EXPR)`.
554 // To avoid ambiguity, the type is surrounded by parentheses.
555 fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
556 self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
557 let expr = self.parse_anon_const_expr()?;
558 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
559 Ok(TyKind::Typeof(expr))
562 /// Parses a function pointer type (`TyKind::BareFn`).
563 /// ```ignore (illustrative)
564 /// [unsafe] [extern "ABI"] fn (S) -> T
565 /// // ^~~~~^ ^~~~^ ^~^ ^
567 /// // | | | Return type
568 /// // Function Style ABI Parameter types
570 /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
574 mut params: Vec<GenericParam>,
575 param_insertion_point: Option<Span>,
576 recover_return_sign: RecoverReturnSign,
577 ) -> PResult<'a, TyKind> {
578 let inherited_vis = rustc_ast::Visibility {
579 span: rustc_span::DUMMY_SP,
580 kind: rustc_ast::VisibilityKind::Inherited,
583 let span_start = self.token.span;
584 let ast::FnHeader { ext, unsafety, constness, asyncness } =
585 self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?;
586 if self.may_recover() && self.token.kind == TokenKind::Lt {
587 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
589 let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
590 let whole_span = lo.to(self.prev_token.span);
591 if let ast::Const::Yes(span) = constness {
592 // If we ever start to allow `const fn()`, then update
593 // feature gating for `#![feature(const_extern_fn)]` to
595 self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span });
597 if let ast::Async::Yes { span, .. } = asyncness {
598 self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
600 let decl_span = span_start.to(self.token.span);
601 Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
604 /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).
605 fn recover_fn_ptr_with_generics(
608 params: &mut Vec<GenericParam>,
609 param_insertion_point: Option<Span>,
610 ) -> PResult<'a, ()> {
611 let generics = self.parse_generics()?;
612 let arity = generics.params.len();
614 let mut lifetimes: Vec<_> = generics
617 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
620 let sugg = if !lifetimes.is_empty() {
622 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
624 let (left, snippet) = if let Some(span) = param_insertion_point {
625 (span, if params.is_empty() { snippet } else { format!(", {snippet}") })
627 (lo.shrink_to_lo(), format!("for<{snippet}> "))
630 Some(FnPtrWithGenericsSugg {
633 right: generics.span,
635 for_param_list_exists: param_insertion_point.is_some(),
641 self.sess.emit_err(FnPtrWithGenerics { span: generics.span, sugg });
642 params.append(&mut lifetimes);
646 /// Parses an `impl B0 + ... + Bn` type.
647 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
648 // Always parse bounds greedily for better error recovery.
649 if self.token.is_lifetime() {
650 self.look_ahead(1, |t| {
651 if let token::Ident(symname, _) = t.kind {
652 // parse pattern with "'a Sized" we're supposed to give suggestion like
654 self.struct_span_err(
656 &format!("expected `+` between lifetime and {}", symname),
658 .span_suggestion_verbose(
659 self.token.span.shrink_to_hi(),
662 Applicability::MaybeIncorrect,
668 let bounds = self.parse_generic_bounds(None)?;
669 *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
670 Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
673 /// Is a `dyn B0 + ... + Bn` type allowed here?
674 fn is_explicit_dyn_type(&mut self) -> bool {
675 self.check_keyword(kw::Dyn)
676 && (!self.token.uninterpolated_span().rust_2015()
677 || self.look_ahead(1, |t| {
678 (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
679 && !can_continue_type_after_non_fn_ident(t)
683 /// Parses a `dyn B0 + ... + Bn` type.
685 /// Note that this does *not* parse bare trait objects.
686 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
687 self.bump(); // `dyn`
690 let syntax = if self.eat(&TokenKind::BinOp(token::Star)) {
691 TraitObjectSyntax::DynStar
693 TraitObjectSyntax::Dyn
696 // Always parse bounds greedily for better error recovery.
697 let bounds = self.parse_generic_bounds(None)?;
698 *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
699 Ok(TyKind::TraitObject(bounds, syntax))
702 /// Parses a type starting with a path.
705 /// 1. a type macro, `mac!(...)`,
706 /// 2. a bare trait object, `B0 + ... + Bn`,
707 /// 3. or a path, `path::to::MyType`.
708 fn parse_path_start_ty(
711 allow_plus: AllowPlus,
712 ty_generics: Option<&Generics>,
713 ) -> PResult<'a, TyKind> {
715 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
716 if self.eat(&token::Not) {
717 // Macro invocation in type position
718 Ok(TyKind::MacCall(P(MacCall {
720 args: self.parse_delim_args()?,
721 prior_type_ascription: self.last_type_ascription,
723 } else if allow_plus == AllowPlus::Yes && self.check_plus() {
724 // `Trait1 + Trait2 + 'a`
725 self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
728 Ok(TyKind::Path(None, path))
732 pub(super) fn parse_generic_bounds(
734 colon_span: Option<Span>,
735 ) -> PResult<'a, GenericBounds> {
736 self.parse_generic_bounds_common(AllowPlus::Yes, colon_span)
739 /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
741 /// See `parse_generic_bound` for the `BOUND` grammar.
742 fn parse_generic_bounds_common(
744 allow_plus: AllowPlus,
745 colon_span: Option<Span>,
746 ) -> PResult<'a, GenericBounds> {
747 let mut bounds = Vec::new();
748 let mut negative_bounds = Vec::new();
750 // In addition to looping while we find generic bounds:
751 // We continue even if we find a keyword. This is necessary for error recovery on,
752 // for example, `impl fn()`. The only keyword that can go after generic bounds is
753 // `where`, so stop if it's it.
754 // We also continue if we find types (not traits), again for error recovery.
755 while self.can_begin_bound()
756 || self.token.can_begin_type()
757 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))
759 if self.token.is_keyword(kw::Dyn) {
760 // Account for `&dyn Trait + dyn Other`.
761 self.sess.emit_err(InvalidDynKeyword { span: self.token.span });
764 match self.parse_generic_bound()? {
765 Ok(bound) => bounds.push(bound),
766 Err(neg_sp) => negative_bounds.push(neg_sp),
768 if allow_plus == AllowPlus::No || !self.eat_plus() {
773 if !negative_bounds.is_empty() {
774 self.error_negative_bounds(colon_span, &bounds, negative_bounds);
780 /// Can the current token begin a bound?
781 fn can_begin_bound(&mut self) -> bool {
782 // This needs to be synchronized with `TokenKind::can_begin_bound`.
784 || self.check_lifetime()
785 || self.check(&token::Not) // Used for error reporting only.
786 || self.check(&token::Question)
787 || self.check(&token::Tilde)
788 || self.check_keyword(kw::For)
789 || self.check(&token::OpenDelim(Delimiter::Parenthesis))
792 fn error_negative_bounds(
794 colon_span: Option<Span>,
795 bounds: &[GenericBound],
796 negative_bounds: Vec<Span>,
798 let sub = if let Some(bound_list) = colon_span {
799 let bound_list = bound_list.to(self.prev_token.span);
800 let mut new_bound_list = String::new();
801 if !bounds.is_empty() {
802 let mut snippets = bounds.iter().map(|bound| self.span_to_snippet(bound.span()));
803 while let Some(Ok(snippet)) = snippets.next() {
804 new_bound_list.push_str(" + ");
805 new_bound_list.push_str(&snippet);
807 new_bound_list = new_bound_list.replacen(" +", ":", 1);
810 Some(NegativeBoundsNotSupportedSugg {
812 num_bounds: negative_bounds.len(),
813 fixed: new_bound_list,
819 let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
820 self.sess.emit_err(NegativeBoundsNotSupported { negative_bounds, last_span, sub });
823 /// Parses a bound according to the grammar:
825 /// BOUND = TY_BOUND | LT_BOUND
827 fn parse_generic_bound(&mut self) -> PResult<'a, Result<GenericBound, Span>> {
828 let anchor_lo = self.prev_token.span;
829 let lo = self.token.span;
830 let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
831 let inner_lo = self.token.span;
832 let is_negative = self.eat(&token::Not);
834 let modifiers = self.parse_ty_bound_modifiers()?;
835 let bound = if self.token.is_lifetime() {
836 self.error_lt_bound_with_modifiers(modifiers);
837 self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
839 self.parse_generic_ty_bound(lo, has_parens, modifiers)?
842 Ok(if is_negative { Err(anchor_lo.to(self.prev_token.span)) } else { Ok(bound) })
845 /// Parses a lifetime ("outlives") bound, e.g. `'a`, according to:
847 /// LT_BOUND = LIFETIME
849 fn parse_generic_lt_bound(
854 ) -> PResult<'a, GenericBound> {
855 let bound = GenericBound::Outlives(self.expect_lifetime());
857 // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
858 // possibly introducing `GenericBound::Paren(P<GenericBound>)`?
859 self.recover_paren_lifetime(lo, inner_lo)?;
864 /// Emits an error if any trait bound modifiers were present.
865 fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
866 if let Some(span) = modifiers.maybe_const {
867 self.struct_span_err(
869 "`~const` may only modify trait bounds, not lifetime bounds",
874 if let Some(span) = modifiers.maybe {
875 self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds")
880 /// Recover on `('lifetime)` with `(` already eaten.
881 fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> {
882 let inner_span = inner_lo.to(self.prev_token.span);
883 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
884 let mut err = self.struct_span_err(
885 lo.to(self.prev_token.span),
886 "parenthesized lifetime bounds are not supported",
888 if let Ok(snippet) = self.span_to_snippet(inner_span) {
889 err.span_suggestion_short(
890 lo.to(self.prev_token.span),
891 "remove the parentheses",
893 Applicability::MachineApplicable,
900 /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `~const Trait`.
902 /// If no modifiers are present, this does not consume any tokens.
905 /// TY_BOUND_MODIFIERS = ["~const"] ["?"]
907 fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> {
908 let maybe_const = if self.eat(&token::Tilde) {
909 let tilde = self.prev_token.span;
910 self.expect_keyword(kw::Const)?;
911 let span = tilde.to(self.prev_token.span);
912 self.sess.gated_spans.gate(sym::const_trait_impl, span);
914 } else if self.eat_keyword(kw::Const) {
915 let span = self.prev_token.span;
916 self.sess.gated_spans.gate(sym::const_trait_impl, span);
918 self.struct_span_err(span, "const bounds must start with `~`")
923 Applicability::MachineApplicable,
932 let maybe = if self.eat(&token::Question) { Some(self.prev_token.span) } else { None };
934 Ok(BoundModifiers { maybe, maybe_const })
937 /// Parses a type bound according to:
939 /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
940 /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
943 /// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`.
944 fn parse_generic_ty_bound(
948 modifiers: BoundModifiers,
949 ) -> PResult<'a, GenericBound> {
950 let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
951 let mut path = if self.token.is_keyword(kw::Fn)
952 && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
953 && let Some(path) = self.recover_path_from_fn()
956 } else if !self.token.is_path_start() && self.token.can_begin_type() {
957 let ty = self.parse_ty_no_plus()?;
958 // Instead of finding a path (a trait), we found a type.
959 let mut err = self.struct_span_err(ty.span, "expected a trait, found type");
961 // If we can recover, try to extract a path from the type. Note
962 // that we do not use the try operator when parsing the type because
963 // if it fails then we get a parser error which we don't want (we're trying
964 // to recover from errors, not make more).
965 let path = if self.may_recover()
966 && matches!(ty.kind, TyKind::Ptr(..) | TyKind::Ref(..))
967 && let TyKind::Path(_, path) = &ty.peel_refs().kind {
968 // Just get the indirection part of the type.
969 let span = ty.span.until(path.span);
971 err.span_suggestion_verbose(
973 "consider removing the indirection",
975 Applicability::MaybeIncorrect,
987 self.parse_path(PathStyle::Type)?
990 if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) {
991 self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?;
995 if self.token.is_like_plus() {
996 // Someone has written something like `&dyn (Trait + Other)`. The correct code
997 // would be `&(dyn Trait + Other)`, but we don't have access to the appropriate
998 // span to suggest that. When written as `&dyn Trait + Other`, an appropriate
999 // suggestion is given.
1000 let bounds = vec![];
1001 self.parse_remaining_bounds(bounds, true)?;
1002 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
1003 let sp = vec![lo, self.prev_token.span];
1004 let sugg = vec![(lo, String::from(" ")), (self.prev_token.span, String::new())];
1005 self.struct_span_err(sp, "incorrect braces around trait bounds")
1006 .multipart_suggestion(
1007 "remove the parentheses",
1009 Applicability::MachineApplicable,
1013 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
1017 let modifier = modifiers.to_trait_bound_modifier();
1018 let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_token.span));
1019 Ok(GenericBound::Trait(poly_trait, modifier))
1022 // recovers a `Fn(..)` parenthesized-style path from `fn(..)`
1023 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1024 let fn_token_span = self.token.span;
1026 let args_lo = self.token.span;
1027 let snapshot = self.create_snapshot_for_diagnostic();
1028 match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1030 self.sess.emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1032 span: fn_token_span.to(self.prev_token.span),
1033 segments: thin_vec![ast::PathSegment {
1034 ident: Ident::new(Symbol::intern("Fn"), fn_token_span),
1036 args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
1037 span: args_lo.to(self.prev_token.span),
1038 inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
1039 inputs_span: args_lo.until(decl.output.span()),
1040 output: decl.output.clone(),
1048 self.restore_snapshot(snapshot);
1054 /// Optionally parses `for<$generic_params>`.
1055 pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
1056 if self.eat_keyword(kw::For) {
1058 let params = self.parse_generic_params()?;
1060 // We rely on AST validation to rule out invalid cases: There must not be type
1061 // parameters, and the lifetime parameters must not have bounds.
1068 /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments
1069 /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already
1071 fn recover_fn_trait_with_lifetime_params(
1073 fn_path: &mut ast::Path,
1074 lifetime_defs: &mut Vec<GenericParam>,
1075 ) -> PResult<'a, ()> {
1076 let fn_path_segment = fn_path.segments.last_mut().unwrap();
1077 let generic_args = if let Some(p_args) = &fn_path_segment.args {
1078 p_args.clone().into_inner()
1080 // Normally it wouldn't come here because the upstream should have parsed
1081 // generic parameters (otherwise it's impossible to call this function).
1085 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1090 if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1091 && let ast::GenericArg::Lifetime(lifetime) = generic_arg {
1101 // Only try to recover if the trait has lifetime params.
1102 if lifetimes.is_empty() {
1106 // Parse `(T, U) -> R`.
1107 let inputs_lo = self.token.span;
1108 let inputs: Vec<_> =
1109 self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
1110 let inputs_span = inputs_lo.to(self.prev_token.span);
1111 let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
1112 let args = ast::ParenthesizedArgs {
1113 span: fn_path_segment.span().to(self.prev_token.span),
1120 ast::PathSegment { ident: fn_path_segment.ident, args, id: ast::DUMMY_NODE_ID };
1122 // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
1123 let mut generic_params = lifetimes
1125 .map(|lt| GenericParam {
1128 attrs: ast::AttrVec::new(),
1130 is_placeholder: false,
1131 kind: ast::GenericParamKind::Lifetime,
1134 .collect::<Vec<GenericParam>>();
1135 lifetime_defs.append(&mut generic_params);
1137 let generic_args_span = generic_args.span();
1139 self.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters");
1140 let snippet = format!(
1142 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1144 let before_fn_path = fn_path.span.shrink_to_lo();
1145 err.multipart_suggestion(
1146 "consider using a higher-ranked trait bound instead",
1147 vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1148 Applicability::MaybeIncorrect,
1154 pub(super) fn check_lifetime(&mut self) -> bool {
1155 self.expected_tokens.push(TokenType::Lifetime);
1156 self.token.is_lifetime()
1159 /// Parses a single lifetime `'a` or panics.
1160 pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1161 if let Some(ident) = self.token.lifetime() {
1163 Lifetime { ident, id: ast::DUMMY_NODE_ID }
1165 self.span_bug(self.token.span, "not a lifetime")
1169 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
1170 P(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })