1 use super::{Parser, PathStyle, TokenType};
3 use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg};
4 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
6 use ast::DUMMY_NODE_ID;
8 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
9 use rustc_ast::util::case::Case;
11 self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
12 MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
14 use rustc_ast_pretty::pprust;
15 use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
16 use rustc_span::source_map::Span;
17 use rustc_span::symbol::{kw, sym, Ident};
18 use rustc_span::Symbol;
19 use thin_vec::thin_vec;
21 /// Any `?` or `~const` modifiers that appear at the start of a bound.
22 struct BoundModifiers {
27 maybe_const: Option<Span>,
31 fn to_trait_bound_modifier(&self) -> TraitBoundModifier {
32 match (self.maybe, self.maybe_const) {
33 (None, None) => TraitBoundModifier::None,
34 (Some(_), None) => TraitBoundModifier::Maybe,
35 (None, Some(_)) => TraitBoundModifier::MaybeConst,
36 (Some(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe,
41 #[derive(Copy, Clone, PartialEq)]
42 pub(super) enum AllowPlus {
47 #[derive(PartialEq, Clone, Copy)]
48 pub(super) enum RecoverQPath {
53 #[derive(PartialEq, Clone, Copy)]
54 pub(super) enum RecoverQuestionMark {
59 #[derive(PartialEq, Clone, Copy)]
60 pub(super) enum RecoverAnonEnum {
65 /// Signals whether parsing a type should recover `->`.
67 /// More specifically, when parsing a function like:
69 /// fn foo() => u8 { 0 }
70 /// fn bar(): u8 { 0 }
72 /// The compiler will try to recover interpreting `foo() => u8` as `foo() -> u8` when calling
73 /// `parse_ty` with anything except `RecoverReturnSign::No`, and it will try to recover `bar(): u8`
74 /// as `bar() -> u8` when passing `RecoverReturnSign::Yes` to `parse_ty`
75 #[derive(Copy, Clone, PartialEq)]
76 pub(super) enum RecoverReturnSign {
82 impl RecoverReturnSign {
83 /// [RecoverReturnSign::Yes] allows for recovering `fn foo() => u8` and `fn foo(): u8`,
84 /// [RecoverReturnSign::OnlyFatArrow] allows for recovering only `fn foo() => u8` (recovering
85 /// colons can cause problems when parsing where clauses), and
86 /// [RecoverReturnSign::No] doesn't allow for any recovery of the return type arrow
87 fn can_recover(self, token: &TokenKind) -> bool {
89 Self::Yes => matches!(token, token::FatArrow | token::Colon),
90 Self::OnlyFatArrow => matches!(token, token::FatArrow),
96 // Is `...` (`CVarArgs`) legal at this level of type parsing?
97 #[derive(PartialEq, Clone, Copy)]
103 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
104 /// `IDENT<<u8 as Trait>::AssocTy>`.
106 /// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
107 /// that `IDENT` is not the ident of a fn trait.
108 fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
109 t == &token::ModSep || t == &token::Lt || t == &token::BinOp(token::Shl)
112 impl<'a> Parser<'a> {
114 pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
115 self.parse_ty_common(
119 RecoverReturnSign::Yes,
121 RecoverQuestionMark::Yes,
126 pub(super) fn parse_ty_with_generics_recovery(
128 ty_params: &Generics,
129 ) -> PResult<'a, P<Ty>> {
130 self.parse_ty_common(
134 RecoverReturnSign::Yes,
136 RecoverQuestionMark::Yes,
141 /// Parse a type suitable for a function or function pointer parameter.
142 /// The difference from `parse_ty` is that this version allows `...`
143 /// (`CVarArgs`) at the top level of the type.
144 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
145 self.parse_ty_common(
149 RecoverReturnSign::Yes,
151 RecoverQuestionMark::Yes,
152 RecoverAnonEnum::Yes,
156 /// Parses a type in restricted contexts where `+` is not permitted.
158 /// Example 1: `&'a TYPE`
159 /// `+` is prohibited to maintain operator priority (P(+) < P(&)).
160 /// Example 2: `value1 as TYPE + value2`
161 /// `+` is prohibited to avoid interactions with expression grammar.
162 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
163 self.parse_ty_common(
167 RecoverReturnSign::Yes,
169 RecoverQuestionMark::Yes,
174 /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin
175 /// for better diagnostics involving `?`.
176 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
177 self.parse_ty_common(
181 RecoverReturnSign::Yes,
183 RecoverQuestionMark::No,
188 pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
189 self.parse_ty_common(
193 RecoverReturnSign::Yes,
195 RecoverQuestionMark::No,
200 /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
201 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
202 self.parse_ty_common(
206 RecoverReturnSign::OnlyFatArrow,
208 RecoverQuestionMark::Yes,
213 /// Parses an optional return type `[ -> TY ]` in a function declaration.
214 pub(super) fn parse_ret_ty(
216 allow_plus: AllowPlus,
217 recover_qpath: RecoverQPath,
218 recover_return_sign: RecoverReturnSign,
219 ) -> PResult<'a, FnRetTy> {
220 Ok(if self.eat(&token::RArrow) {
221 // FIXME(Centril): Can we unconditionally `allow_plus`?
222 let ty = self.parse_ty_common(
228 RecoverQuestionMark::Yes,
229 RecoverAnonEnum::Yes,
232 } else if recover_return_sign.can_recover(&self.token.kind) {
233 // Don't `eat` to prevent `=>` from being added as an expected token which isn't
234 // actually expected and could only confuse users
236 self.struct_span_err(self.prev_token.span, "return types are denoted using `->`")
237 .span_suggestion_short(
238 self.prev_token.span,
241 Applicability::MachineApplicable,
244 let ty = self.parse_ty_common(
250 RecoverQuestionMark::Yes,
251 RecoverAnonEnum::Yes,
255 FnRetTy::Default(self.token.span.shrink_to_lo())
261 allow_plus: AllowPlus,
262 allow_c_variadic: AllowCVariadic,
263 recover_qpath: RecoverQPath,
264 recover_return_sign: RecoverReturnSign,
265 ty_generics: Option<&Generics>,
266 recover_question_mark: RecoverQuestionMark,
267 recover_anon_enum: RecoverAnonEnum,
268 ) -> PResult<'a, P<Ty>> {
269 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
270 maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
271 maybe_whole!(self, NtTy, |x| x);
273 let lo = self.token.span;
274 let mut impl_dyn_multi = false;
275 let kind = if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
276 self.parse_ty_tuple_or_parens(lo, allow_plus)?
277 } else if self.eat(&token::Not) {
280 } else if self.eat(&token::BinOp(token::Star)) {
282 } else if self.eat(&token::OpenDelim(Delimiter::Bracket)) {
283 self.parse_array_or_slice_ty()?
284 } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) {
287 self.parse_borrowed_pointee()?
288 } else if self.eat_keyword_noexpect(kw::Typeof) {
289 self.parse_typeof_ty()?
290 } else if self.eat_keyword(kw::Underscore) {
291 // A type to be inferred `_`
293 } else if self.check_fn_front_matter(false, Case::Sensitive) {
294 // Function pointer type
295 self.parse_ty_bare_fn(lo, Vec::new(), None, recover_return_sign)?
296 } else if self.check_keyword(kw::For) {
297 // Function pointer type or bound list (trait object type) starting with a poly-trait.
298 // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
299 // `for<'lt> Trait1<'lt> + Trait2 + 'a`
300 let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
301 if self.check_fn_front_matter(false, Case::Sensitive) {
302 self.parse_ty_bare_fn(
305 Some(self.prev_token.span.shrink_to_lo()),
309 let path = self.parse_path(PathStyle::Type)?;
310 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
311 self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
313 } else if self.eat_keyword(kw::Impl) {
314 self.parse_impl_ty(&mut impl_dyn_multi)?
315 } else if self.is_explicit_dyn_type() {
316 self.parse_dyn_ty(&mut impl_dyn_multi)?
317 } else if self.eat_lt() {
319 let (qself, path) = self.parse_qpath(PathStyle::Type)?;
320 TyKind::Path(Some(qself), path)
321 } else if self.check_path() {
322 self.parse_path_start_ty(lo, allow_plus, ty_generics)?
323 } else if self.can_begin_bound() {
324 self.parse_bare_trait_object(lo, allow_plus)?
325 } else if self.eat(&token::DotDotDot) {
326 if allow_c_variadic == AllowCVariadic::Yes {
329 // FIXME(Centril): Should we just allow `...` syntactically
330 // anywhere in a type and use semantic restrictions instead?
331 self.error_illegal_c_varadic_ty(lo);
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.
346 if allow_plus == AllowPlus::Yes {
347 self.maybe_recover_from_bad_type_plus(&ty)?;
349 self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty);
351 if RecoverQuestionMark::Yes == recover_question_mark {
352 ty = self.maybe_recover_from_question_mark(ty);
354 if recover_anon_enum == RecoverAnonEnum::Yes
355 && self.check_noexpect(&token::BinOp(token::Or))
356 && self.look_ahead(1, |t| t.can_begin_type())
358 let mut pipes = vec![self.token.span];
359 let mut types = vec![ty];
361 if !self.eat(&token::BinOp(token::Or)) {
364 pipes.push(self.prev_token.span);
365 types.push(self.parse_ty_common(
371 recover_question_mark,
375 let mut err = self.struct_span_err(pipes, "anonymous enums are not supported");
377 err.span_label(ty.span, "");
380 "create a named `enum` and use it here instead:\nenum Name {{\n{}\n}}",
384 .map(|(i, t)| format!(
386 i + 1, // Lets not confuse people with zero-indexing :)
387 pprust::to_string(|s| s.print_type(&t)),
393 return Ok(self.mk_ty(lo.to(self.prev_token.span), TyKind::Err));
395 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
399 /// - `(TYPE)`, a parenthesized type.
400 /// - `(TYPE,)`, a tuple with a single field of type TYPE.
401 fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
402 let mut trailing_plus = false;
403 let (ts, trailing) = self.parse_paren_comma_seq(|p| {
404 let ty = p.parse_ty()?;
405 trailing_plus = p.prev_token.kind == TokenKind::BinOp(token::Plus);
409 if ts.len() == 1 && !trailing {
410 let ty = ts.into_iter().next().unwrap().into_inner();
411 let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
413 // `(TY_BOUND_NOPAREN) + BOUND + ...`.
414 TyKind::Path(None, path) if maybe_bounds => {
415 self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
417 TyKind::TraitObject(bounds, TraitObjectSyntax::None)
418 if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
420 self.parse_remaining_bounds(bounds, true)
423 _ => Ok(TyKind::Paren(P(ty))),
430 fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
431 let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
432 let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
434 self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`")
437 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
440 fn parse_remaining_bounds_path(
442 generic_params: Vec<GenericParam>,
446 ) -> PResult<'a, TyKind> {
447 let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span));
448 let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
449 self.parse_remaining_bounds(bounds, parse_plus)
452 /// Parse the remainder of a bare trait object type given an already parsed list.
453 fn parse_remaining_bounds(
455 mut bounds: GenericBounds,
457 ) -> PResult<'a, TyKind> {
459 self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
460 bounds.append(&mut self.parse_generic_bounds(Some(self.prev_token.span))?);
462 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
465 /// Parses a raw pointer type: `*[const | mut] $type`.
466 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
467 let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
468 let span = self.prev_token.span;
469 self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type")
472 "add `mut` or `const` here",
473 ["mut ".to_string(), "const ".to_string()],
474 Applicability::HasPlaceholders,
479 let ty = self.parse_ty_no_plus()?;
480 Ok(TyKind::Ptr(MutTy { ty, mutbl }))
483 /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
484 /// The opening `[` bracket is already eaten.
485 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
486 let elt_ty = match self.parse_ty() {
489 if self.look_ahead(1, |t| t.kind == token::CloseDelim(Delimiter::Bracket))
490 | self.look_ahead(1, |t| t.kind == token::Semi) =>
492 // Recover from `[LIT; EXPR]` and `[LIT]`
495 self.mk_ty(self.prev_token.span, TyKind::Err)
497 Err(err) => return Err(err),
500 let ty = if self.eat(&token::Semi) {
501 let mut length = self.parse_anon_const_expr()?;
502 if let Err(e) = self.expect(&token::CloseDelim(Delimiter::Bracket)) {
503 // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
504 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
505 self.expect(&token::CloseDelim(Delimiter::Bracket))?;
507 TyKind::Array(elt_ty, length)
509 self.expect(&token::CloseDelim(Delimiter::Bracket))?;
510 TyKind::Slice(elt_ty)
516 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
517 let and_span = self.prev_token.span;
518 let mut opt_lifetime =
519 if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
520 let mut mutbl = self.parse_mutability();
521 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
522 // A lifetime is invalid here: it would be part of a bare trait bound, which requires
523 // it to be followed by a plus, but we disallow plus in the pointee type.
524 // So we can handle this case as an error here, and suggest `'a mut`.
525 // If there *is* a plus next though, handling the error later provides better suggestions
526 // (like adding parentheses)
527 if !self.look_ahead(1, |t| t.is_like_plus()) {
528 let lifetime_span = self.token.span;
529 let span = and_span.to(lifetime_span);
531 let mut err = self.struct_span_err(span, "lifetime must precede `mut`");
532 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
535 "place the lifetime before `mut`",
536 format!("&{} mut", lifetime_src),
537 Applicability::MaybeIncorrect,
542 opt_lifetime = Some(self.expect_lifetime());
544 } else if self.token.is_keyword(kw::Dyn)
545 && mutbl == Mutability::Not
546 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
548 // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
549 let span = and_span.to(self.look_ahead(1, |t| t.span));
550 let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
553 "place `mut` before `dyn`",
555 Applicability::MachineApplicable,
560 mutbl = Mutability::Mut;
561 let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing);
563 self.bump_with((dyn_tok, dyn_tok_sp));
565 let ty = self.parse_ty_no_plus()?;
566 Ok(TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }))
569 // Parses the `typeof(EXPR)`.
570 // To avoid ambiguity, the type is surrounded by parentheses.
571 fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
572 self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
573 let expr = self.parse_anon_const_expr()?;
574 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
575 Ok(TyKind::Typeof(expr))
578 /// Parses a function pointer type (`TyKind::BareFn`).
579 /// ```ignore (illustrative)
580 /// [unsafe] [extern "ABI"] fn (S) -> T
581 /// // ^~~~~^ ^~~~^ ^~^ ^
583 /// // | | | Return type
584 /// // Function Style ABI Parameter types
586 /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
590 mut params: Vec<GenericParam>,
591 param_insertion_point: Option<Span>,
592 recover_return_sign: RecoverReturnSign,
593 ) -> PResult<'a, TyKind> {
594 let inherited_vis = rustc_ast::Visibility {
595 span: rustc_span::DUMMY_SP,
596 kind: rustc_ast::VisibilityKind::Inherited,
599 let span_start = self.token.span;
600 let ast::FnHeader { ext, unsafety, constness, asyncness } =
601 self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?;
602 if self.may_recover() && self.token.kind == TokenKind::Lt {
603 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
605 let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
606 let whole_span = lo.to(self.prev_token.span);
607 if let ast::Const::Yes(span) = constness {
608 // If we ever start to allow `const fn()`, then update
609 // feature gating for `#![feature(const_extern_fn)]` to
611 self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
613 if let ast::Async::Yes { span, .. } = asyncness {
614 self.error_fn_ptr_bad_qualifier(whole_span, span, "async");
616 let decl_span = span_start.to(self.token.span);
617 Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
620 /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).
621 fn recover_fn_ptr_with_generics(
624 params: &mut Vec<GenericParam>,
625 param_insertion_point: Option<Span>,
626 ) -> PResult<'a, ()> {
627 let generics = self.parse_generics()?;
628 let arity = generics.params.len();
630 let mut lifetimes: Vec<_> = generics
633 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
636 let sugg = if !lifetimes.is_empty() {
638 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
640 let (left, snippet) = if let Some(span) = param_insertion_point {
641 (span, if params.is_empty() { snippet } else { format!(", {snippet}") })
643 (lo.shrink_to_lo(), format!("for<{snippet}> "))
646 Some(FnPtrWithGenericsSugg {
649 right: generics.span,
651 for_param_list_exists: param_insertion_point.is_some(),
657 self.sess.emit_err(FnPtrWithGenerics { span: generics.span, sugg });
658 params.append(&mut lifetimes);
662 /// Emit an error for the given bad function pointer qualifier.
663 fn error_fn_ptr_bad_qualifier(&self, span: Span, qual_span: Span, qual: &str) {
664 self.struct_span_err(span, &format!("an `fn` pointer type cannot be `{}`", qual))
665 .span_label(qual_span, format!("`{}` because of this", qual))
666 .span_suggestion_short(
668 &format!("remove the `{}` qualifier", qual),
670 Applicability::MaybeIncorrect,
675 /// Parses an `impl B0 + ... + Bn` type.
676 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
677 // Always parse bounds greedily for better error recovery.
678 if self.token.is_lifetime() {
679 self.look_ahead(1, |t| {
680 if let token::Ident(symname, _) = t.kind {
681 // parse pattern with "'a Sized" we're supposed to give suggestion like
683 self.struct_span_err(
685 &format!("expected `+` between lifetime and {}", symname),
687 .span_suggestion_verbose(
688 self.token.span.shrink_to_hi(),
691 Applicability::MaybeIncorrect,
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::ImplTrait(ast::DUMMY_NODE_ID, bounds))
702 /// Is a `dyn B0 + ... + Bn` type allowed here?
703 fn is_explicit_dyn_type(&mut self) -> bool {
704 self.check_keyword(kw::Dyn)
705 && (!self.token.uninterpolated_span().rust_2015()
706 || self.look_ahead(1, |t| {
707 (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
708 && !can_continue_type_after_non_fn_ident(t)
712 /// Parses a `dyn B0 + ... + Bn` type.
714 /// Note that this does *not* parse bare trait objects.
715 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
716 self.bump(); // `dyn`
719 let syntax = if self.eat(&TokenKind::BinOp(token::Star)) {
720 TraitObjectSyntax::DynStar
722 TraitObjectSyntax::Dyn
725 // Always parse bounds greedily for better error recovery.
726 let bounds = self.parse_generic_bounds(None)?;
727 *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
728 Ok(TyKind::TraitObject(bounds, syntax))
731 /// Parses a type starting with a path.
734 /// 1. a type macro, `mac!(...)`,
735 /// 2. a bare trait object, `B0 + ... + Bn`,
736 /// 3. or a path, `path::to::MyType`.
737 fn parse_path_start_ty(
740 allow_plus: AllowPlus,
741 ty_generics: Option<&Generics>,
742 ) -> PResult<'a, TyKind> {
744 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
745 if self.eat(&token::Not) {
746 // Macro invocation in type position
747 Ok(TyKind::MacCall(P(MacCall {
749 args: self.parse_delim_args()?,
750 prior_type_ascription: self.last_type_ascription,
752 } else if allow_plus == AllowPlus::Yes && self.check_plus() {
753 // `Trait1 + Trait2 + 'a`
754 self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
757 Ok(TyKind::Path(None, path))
761 fn error_illegal_c_varadic_ty(&self, lo: Span) {
763 self.sess.span_diagnostic,
764 lo.to(self.prev_token.span),
766 "C-variadic type `...` may not be nested inside another type",
771 pub(super) fn parse_generic_bounds(
773 colon_span: Option<Span>,
774 ) -> PResult<'a, GenericBounds> {
775 self.parse_generic_bounds_common(AllowPlus::Yes, colon_span)
778 /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
780 /// See `parse_generic_bound` for the `BOUND` grammar.
781 fn parse_generic_bounds_common(
783 allow_plus: AllowPlus,
784 colon_span: Option<Span>,
785 ) -> PResult<'a, GenericBounds> {
786 let mut bounds = Vec::new();
787 let mut negative_bounds = Vec::new();
789 // In addition to looping while we find generic bounds:
790 // We continue even if we find a keyword. This is necessary for error recovery on,
791 // for example, `impl fn()`. The only keyword that can go after generic bounds is
792 // `where`, so stop if it's it.
793 // We also continue if we find types (not traits), again for error recovery.
794 while self.can_begin_bound()
795 || self.token.can_begin_type()
796 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))
798 if self.token.is_keyword(kw::Dyn) {
799 // Account for `&dyn Trait + dyn Other`.
800 self.struct_span_err(self.token.span, "invalid `dyn` keyword")
801 .help("`dyn` is only needed at the start of a trait `+`-separated list")
804 "remove this keyword",
806 Applicability::MachineApplicable,
811 match self.parse_generic_bound()? {
812 Ok(bound) => bounds.push(bound),
813 Err(neg_sp) => negative_bounds.push(neg_sp),
815 if allow_plus == AllowPlus::No || !self.eat_plus() {
820 if !negative_bounds.is_empty() {
821 self.error_negative_bounds(colon_span, &bounds, negative_bounds);
827 /// Can the current token begin a bound?
828 fn can_begin_bound(&mut self) -> bool {
829 // This needs to be synchronized with `TokenKind::can_begin_bound`.
831 || self.check_lifetime()
832 || self.check(&token::Not) // Used for error reporting only.
833 || self.check(&token::Question)
834 || self.check(&token::Tilde)
835 || self.check_keyword(kw::For)
836 || self.check(&token::OpenDelim(Delimiter::Parenthesis))
839 fn error_negative_bounds(
841 colon_span: Option<Span>,
842 bounds: &[GenericBound],
843 negative_bounds: Vec<Span>,
845 let negative_bounds_len = negative_bounds.len();
846 let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
847 let mut err = self.struct_span_err(negative_bounds, "negative bounds are not supported");
848 err.span_label(last_span, "negative bounds are not supported");
849 if let Some(bound_list) = colon_span {
850 let bound_list = bound_list.to(self.prev_token.span);
851 let mut new_bound_list = String::new();
852 if !bounds.is_empty() {
853 let mut snippets = bounds.iter().map(|bound| self.span_to_snippet(bound.span()));
854 while let Some(Ok(snippet)) = snippets.next() {
855 new_bound_list.push_str(" + ");
856 new_bound_list.push_str(&snippet);
858 new_bound_list = new_bound_list.replacen(" +", ":", 1);
860 err.tool_only_span_suggestion(
862 &format!("remove the bound{}", pluralize!(negative_bounds_len)),
864 Applicability::MachineApplicable,
870 /// Parses a bound according to the grammar:
872 /// BOUND = TY_BOUND | LT_BOUND
874 fn parse_generic_bound(&mut self) -> PResult<'a, Result<GenericBound, Span>> {
875 let anchor_lo = self.prev_token.span;
876 let lo = self.token.span;
877 let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
878 let inner_lo = self.token.span;
879 let is_negative = self.eat(&token::Not);
881 let modifiers = self.parse_ty_bound_modifiers()?;
882 let bound = if self.token.is_lifetime() {
883 self.error_lt_bound_with_modifiers(modifiers);
884 self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
886 self.parse_generic_ty_bound(lo, has_parens, modifiers)?
889 Ok(if is_negative { Err(anchor_lo.to(self.prev_token.span)) } else { Ok(bound) })
892 /// Parses a lifetime ("outlives") bound, e.g. `'a`, according to:
894 /// LT_BOUND = LIFETIME
896 fn parse_generic_lt_bound(
901 ) -> PResult<'a, GenericBound> {
902 let bound = GenericBound::Outlives(self.expect_lifetime());
904 // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
905 // possibly introducing `GenericBound::Paren(P<GenericBound>)`?
906 self.recover_paren_lifetime(lo, inner_lo)?;
911 /// Emits an error if any trait bound modifiers were present.
912 fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
913 if let Some(span) = modifiers.maybe_const {
914 self.struct_span_err(
916 "`~const` may only modify trait bounds, not lifetime bounds",
921 if let Some(span) = modifiers.maybe {
922 self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds")
927 /// Recover on `('lifetime)` with `(` already eaten.
928 fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> {
929 let inner_span = inner_lo.to(self.prev_token.span);
930 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
931 let mut err = self.struct_span_err(
932 lo.to(self.prev_token.span),
933 "parenthesized lifetime bounds are not supported",
935 if let Ok(snippet) = self.span_to_snippet(inner_span) {
936 err.span_suggestion_short(
937 lo.to(self.prev_token.span),
938 "remove the parentheses",
940 Applicability::MachineApplicable,
947 /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `~const Trait`.
949 /// If no modifiers are present, this does not consume any tokens.
952 /// TY_BOUND_MODIFIERS = ["~const"] ["?"]
954 fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> {
955 let maybe_const = if self.eat(&token::Tilde) {
956 let tilde = self.prev_token.span;
957 self.expect_keyword(kw::Const)?;
958 let span = tilde.to(self.prev_token.span);
959 self.sess.gated_spans.gate(sym::const_trait_impl, span);
961 } else if self.eat_keyword(kw::Const) {
962 let span = self.prev_token.span;
963 self.sess.gated_spans.gate(sym::const_trait_impl, span);
965 self.struct_span_err(span, "const bounds must start with `~`")
970 Applicability::MachineApplicable,
979 let maybe = if self.eat(&token::Question) { Some(self.prev_token.span) } else { None };
981 Ok(BoundModifiers { maybe, maybe_const })
984 /// Parses a type bound according to:
986 /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
987 /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
990 /// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`.
991 fn parse_generic_ty_bound(
995 modifiers: BoundModifiers,
996 ) -> PResult<'a, GenericBound> {
997 let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
998 let mut path = if self.token.is_keyword(kw::Fn)
999 && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
1000 && let Some(path) = self.recover_path_from_fn()
1003 } else if !self.token.is_path_start() && self.token.can_begin_type() {
1004 let ty = self.parse_ty_no_plus()?;
1005 // Instead of finding a path (a trait), we found a type.
1006 let mut err = self.struct_span_err(ty.span, "expected a trait, found type");
1008 // If we can recover, try to extract a path from the type. Note
1009 // that we do not use the try operator when parsing the type because
1010 // if it fails then we get a parser error which we don't want (we're trying
1011 // to recover from errors, not make more).
1012 let path = if self.may_recover()
1013 && matches!(ty.kind, TyKind::Ptr(..) | TyKind::Ref(..))
1014 && let TyKind::Path(_, path) = &ty.peel_refs().kind {
1015 // Just get the indirection part of the type.
1016 let span = ty.span.until(path.span);
1018 err.span_suggestion_verbose(
1020 "consider removing the indirection",
1022 Applicability::MaybeIncorrect,
1034 self.parse_path(PathStyle::Type)?
1037 if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) {
1038 self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?;
1042 if self.token.is_like_plus() {
1043 // Someone has written something like `&dyn (Trait + Other)`. The correct code
1044 // would be `&(dyn Trait + Other)`, but we don't have access to the appropriate
1045 // span to suggest that. When written as `&dyn Trait + Other`, an appropriate
1046 // suggestion is given.
1047 let bounds = vec![];
1048 self.parse_remaining_bounds(bounds, true)?;
1049 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
1050 let sp = vec![lo, self.prev_token.span];
1051 let sugg = vec![(lo, String::from(" ")), (self.prev_token.span, String::new())];
1052 self.struct_span_err(sp, "incorrect braces around trait bounds")
1053 .multipart_suggestion(
1054 "remove the parentheses",
1056 Applicability::MachineApplicable,
1060 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
1064 let modifier = modifiers.to_trait_bound_modifier();
1065 let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_token.span));
1066 Ok(GenericBound::Trait(poly_trait, modifier))
1069 // recovers a `Fn(..)` parenthesized-style path from `fn(..)`
1070 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1071 let fn_token_span = self.token.span;
1073 let args_lo = self.token.span;
1074 let snapshot = self.create_snapshot_for_diagnostic();
1075 match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1077 self.sess.emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1079 span: fn_token_span.to(self.prev_token.span),
1080 segments: thin_vec![ast::PathSegment {
1081 ident: Ident::new(Symbol::intern("Fn"), fn_token_span),
1083 args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
1084 span: args_lo.to(self.prev_token.span),
1085 inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
1086 inputs_span: args_lo.until(decl.output.span()),
1087 output: decl.output.clone(),
1095 self.restore_snapshot(snapshot);
1101 /// Optionally parses `for<$generic_params>`.
1102 pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
1103 if self.eat_keyword(kw::For) {
1105 let params = self.parse_generic_params()?;
1107 // We rely on AST validation to rule out invalid cases: There must not be type
1108 // parameters, and the lifetime parameters must not have bounds.
1115 /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments
1116 /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already
1118 fn recover_fn_trait_with_lifetime_params(
1120 fn_path: &mut ast::Path,
1121 lifetime_defs: &mut Vec<GenericParam>,
1122 ) -> PResult<'a, ()> {
1123 let fn_path_segment = fn_path.segments.last_mut().unwrap();
1124 let generic_args = if let Some(p_args) = &fn_path_segment.args {
1125 p_args.clone().into_inner()
1127 // Normally it wouldn't come here because the upstream should have parsed
1128 // generic parameters (otherwise it's impossible to call this function).
1132 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1137 if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1138 && let ast::GenericArg::Lifetime(lifetime) = generic_arg {
1148 // Only try to recover if the trait has lifetime params.
1149 if lifetimes.is_empty() {
1153 // Parse `(T, U) -> R`.
1154 let inputs_lo = self.token.span;
1155 let inputs: Vec<_> =
1156 self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
1157 let inputs_span = inputs_lo.to(self.prev_token.span);
1158 let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
1159 let args = ast::ParenthesizedArgs {
1160 span: fn_path_segment.span().to(self.prev_token.span),
1167 ast::PathSegment { ident: fn_path_segment.ident, args, id: ast::DUMMY_NODE_ID };
1169 // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
1170 let mut generic_params = lifetimes
1172 .map(|lt| GenericParam {
1175 attrs: ast::AttrVec::new(),
1177 is_placeholder: false,
1178 kind: ast::GenericParamKind::Lifetime,
1181 .collect::<Vec<GenericParam>>();
1182 lifetime_defs.append(&mut generic_params);
1184 let generic_args_span = generic_args.span();
1186 self.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters");
1187 let snippet = format!(
1189 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1191 let before_fn_path = fn_path.span.shrink_to_lo();
1192 err.multipart_suggestion(
1193 "consider using a higher-ranked trait bound instead",
1194 vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1195 Applicability::MaybeIncorrect,
1201 pub(super) fn check_lifetime(&mut self) -> bool {
1202 self.expected_tokens.push(TokenType::Lifetime);
1203 self.token.is_lifetime()
1206 /// Parses a single lifetime `'a` or panics.
1207 pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1208 if let Some(ident) = self.token.lifetime() {
1210 Lifetime { ident, id: ast::DUMMY_NODE_ID }
1212 self.span_bug(self.token.span, "not a lifetime")
1216 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
1217 P(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })