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, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, 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 FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
19 HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
20 NestedCVariadicType, ReturnTypesUseThinArrow,
21};
22use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
23
24#[derive(Copy, Clone, PartialEq)]
30pub(super) enum AllowPlus {
31 Yes,
32 No,
33}
34
35#[derive(PartialEq)]
36pub(super) enum RecoverQPath {
37 Yes,
38 No,
39}
40
41pub(super) enum RecoverQuestionMark {
42 Yes,
43 No,
44}
45
46#[derive(Copy, Clone, PartialEq)]
57pub(super) enum RecoverReturnSign {
58 Yes,
59 OnlyFatArrow,
60 No,
61}
62
63impl RecoverReturnSign {
64 fn can_recover(self, token: &TokenKind) -> bool {
69 match self {
70 Self::Yes => matches!(token, token::FatArrow | token::Colon),
71 Self::OnlyFatArrow => matches!(token, token::FatArrow),
72 Self::No => false,
73 }
74 }
75}
76
77#[derive(PartialEq)]
79enum AllowCVariadic {
80 Yes,
81 No,
82}
83
84fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
90 t == &token::PathSep || t == &token::Lt || t == &token::Shl
91}
92
93fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
94 t.is_path_start()
99 || t.is_lifetime()
100 || t == &TokenKind::Question
101 || t.is_keyword(kw::For)
102 || t == &TokenKind::OpenParen
103}
104
105impl<'a> Parser<'a> {
106 pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
108 ensure_sufficient_stack(|| {
110 self.parse_ty_common(
111 AllowPlus::Yes,
112 AllowCVariadic::No,
113 RecoverQPath::Yes,
114 RecoverReturnSign::Yes,
115 None,
116 RecoverQuestionMark::Yes,
117 )
118 })
119 }
120
121 pub(super) fn parse_ty_with_generics_recovery(
122 &mut self,
123 ty_params: &Generics,
124 ) -> PResult<'a, P<Ty>> {
125 self.parse_ty_common(
126 AllowPlus::Yes,
127 AllowCVariadic::No,
128 RecoverQPath::Yes,
129 RecoverReturnSign::Yes,
130 Some(ty_params),
131 RecoverQuestionMark::Yes,
132 )
133 }
134
135 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
139 self.parse_ty_common(
140 AllowPlus::Yes,
141 AllowCVariadic::Yes,
142 RecoverQPath::Yes,
143 RecoverReturnSign::Yes,
144 None,
145 RecoverQuestionMark::Yes,
146 )
147 }
148
149 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
156 self.parse_ty_common(
157 AllowPlus::No,
158 AllowCVariadic::No,
159 RecoverQPath::Yes,
160 RecoverReturnSign::Yes,
161 None,
162 RecoverQuestionMark::Yes,
163 )
164 }
165
166 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
169 self.parse_ty_common(
170 AllowPlus::No,
171 AllowCVariadic::No,
172 RecoverQPath::Yes,
173 RecoverReturnSign::Yes,
174 None,
175 RecoverQuestionMark::No,
176 )
177 }
178
179 pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
180 self.parse_ty_common(
181 AllowPlus::Yes,
182 AllowCVariadic::No,
183 RecoverQPath::Yes,
184 RecoverReturnSign::Yes,
185 None,
186 RecoverQuestionMark::No,
187 )
188 }
189
190 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
193 self.parse_ty_common(
194 AllowPlus::Yes,
195 AllowCVariadic::No,
196 RecoverQPath::Yes,
197 RecoverReturnSign::OnlyFatArrow,
198 None,
199 RecoverQuestionMark::Yes,
200 )
201 }
202
203 pub(super) fn parse_ret_ty(
205 &mut self,
206 allow_plus: AllowPlus,
207 recover_qpath: RecoverQPath,
208 recover_return_sign: RecoverReturnSign,
209 ) -> PResult<'a, FnRetTy> {
210 let lo = self.prev_token.span;
211 Ok(if self.eat(exp!(RArrow)) {
212 let ty = self.parse_ty_common(
214 allow_plus,
215 AllowCVariadic::No,
216 recover_qpath,
217 recover_return_sign,
218 None,
219 RecoverQuestionMark::Yes,
220 )?;
221 FnRetTy::Ty(ty)
222 } else if recover_return_sign.can_recover(&self.token.kind) {
223 self.bump();
226 self.dcx().emit_err(ReturnTypesUseThinArrow {
227 span: self.prev_token.span,
228 suggestion: lo.between(self.token.span),
229 });
230 let ty = self.parse_ty_common(
231 allow_plus,
232 AllowCVariadic::No,
233 recover_qpath,
234 recover_return_sign,
235 None,
236 RecoverQuestionMark::Yes,
237 )?;
238 FnRetTy::Ty(ty)
239 } else {
240 FnRetTy::Default(self.prev_token.span.shrink_to_hi())
241 })
242 }
243
244 fn parse_ty_common(
245 &mut self,
246 allow_plus: AllowPlus,
247 allow_c_variadic: AllowCVariadic,
248 recover_qpath: RecoverQPath,
249 recover_return_sign: RecoverReturnSign,
250 ty_generics: Option<&Generics>,
251 recover_question_mark: RecoverQuestionMark,
252 ) -> PResult<'a, P<Ty>> {
253 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
254 maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
255
256 if let Some(ty) = self.eat_metavar_seq_with_matcher(
257 |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
258 |this| this.parse_ty_no_question_mark_recover(),
259 ) {
260 return Ok(ty);
261 }
262
263 let lo = self.token.span;
264 let mut impl_dyn_multi = false;
265 let kind = if self.check(exp!(OpenParen)) {
266 self.parse_ty_tuple_or_parens(lo, allow_plus)?
267 } else if self.eat(exp!(Bang)) {
268 TyKind::Never
270 } else if self.eat(exp!(Star)) {
271 self.parse_ty_ptr()?
272 } else if self.eat(exp!(OpenBracket)) {
273 self.parse_array_or_slice_ty()?
274 } else if self.check(exp!(And)) || self.check(exp!(AndAnd)) {
275 self.expect_and()?;
277 self.parse_borrowed_pointee()?
278 } else if self.eat_keyword_noexpect(kw::Typeof) {
279 self.parse_typeof_ty()?
280 } else if self.eat_keyword(exp!(Underscore)) {
281 TyKind::Infer
283 } else if self.check_fn_front_matter(false, Case::Sensitive) {
284 self.parse_ty_bare_fn(lo, ThinVec::new(), None, recover_return_sign)?
286 } else if self.check_keyword(exp!(For)) {
287 let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
291 if self.check_fn_front_matter(false, Case::Sensitive) {
292 self.parse_ty_bare_fn(
293 lo,
294 lifetime_defs,
295 Some(self.prev_token.span.shrink_to_lo()),
296 recover_return_sign,
297 )?
298 } else {
299 if self.may_recover()
301 && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))
302 {
303 let kw = self.prev_token.ident().unwrap().0;
304 let removal_span = kw.span.with_hi(self.token.span.lo());
305 let path = self.parse_path(PathStyle::Type)?;
306 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
307 let kind =
308 self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?;
309 let err = self.dcx().create_err(errors::TransposeDynOrImpl {
310 span: kw.span,
311 kw: kw.name.as_str(),
312 sugg: errors::TransposeDynOrImplSugg {
313 removal_span,
314 insertion_span: lo.shrink_to_lo(),
315 kw: kw.name.as_str(),
316 },
317 });
318
319 let kind = match (kind, kw.name) {
322 (TyKind::TraitObject(bounds, _), kw::Dyn) => {
323 TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
324 }
325 (TyKind::TraitObject(bounds, _), kw::Impl) => {
326 TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
327 }
328 _ => return Err(err),
329 };
330 err.emit();
331 kind
332 } else {
333 let path = self.parse_path(PathStyle::Type)?;
334 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
335 self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
336 }
337 }
338 } else if self.eat_keyword(exp!(Impl)) {
339 self.parse_impl_ty(&mut impl_dyn_multi)?
340 } else if self.is_explicit_dyn_type() {
341 self.parse_dyn_ty(&mut impl_dyn_multi)?
342 } else if self.eat_lt() {
343 let (qself, path) = self.parse_qpath(PathStyle::Type)?;
345 TyKind::Path(Some(qself), path)
346 } else if self.check_path() {
347 self.parse_path_start_ty(lo, allow_plus, ty_generics)?
348 } else if self.can_begin_bound() {
349 self.parse_bare_trait_object(lo, allow_plus)?
350 } else if self.eat(exp!(DotDotDot)) {
351 match allow_c_variadic {
352 AllowCVariadic::Yes => TyKind::CVarArgs,
353 AllowCVariadic::No => {
354 let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });
358 TyKind::Err(guar)
359 }
360 }
361 } else if self.check_keyword(exp!(Unsafe))
362 && self.look_ahead(1, |tok| tok.kind == token::Lt)
363 {
364 self.parse_unsafe_binder_ty()?
365 } else {
366 let msg = format!("expected type, found {}", super::token_descr(&self.token));
367 let mut err = self.dcx().struct_span_err(lo, msg);
368 err.span_label(lo, "expected type");
369 return Err(err);
370 };
371
372 let span = lo.to(self.prev_token.span);
373 let mut ty = self.mk_ty(span, kind);
374
375 match allow_plus {
377 AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
378 AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
379 }
380 if let RecoverQuestionMark::Yes = recover_question_mark {
381 ty = self.maybe_recover_from_question_mark(ty);
382 }
383 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
384 }
385
386 fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
387 let lo = self.token.span;
388 assert!(self.eat_keyword(exp!(Unsafe)));
389 self.expect_lt()?;
390 let generic_params = self.parse_generic_params()?;
391 self.expect_gt()?;
392 let inner_ty = self.parse_ty()?;
393 let span = lo.to(self.prev_token.span);
394 self.psess.gated_spans.gate(sym::unsafe_binders, span);
395
396 Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty })))
397 }
398
399 fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
403 let mut trailing_plus = false;
404 let (ts, trailing) = self.parse_paren_comma_seq(|p| {
405 let ty = p.parse_ty()?;
406 trailing_plus = p.prev_token == TokenKind::Plus;
407 Ok(ty)
408 })?;
409
410 if ts.len() == 1 && matches!(trailing, Trailing::No) {
411 let ty = ts.into_iter().next().unwrap().into_inner();
412 let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
413 match ty.kind {
414 TyKind::Path(None, path) if maybe_bounds => {
416 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
417 }
418 TyKind::TraitObject(bounds, TraitObjectSyntax::None)
422 if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
423 {
424 self.parse_remaining_bounds(bounds, true)
425 }
426 _ => Ok(TyKind::Paren(P(ty))),
428 }
429 } else {
430 Ok(TyKind::Tup(ts))
431 }
432 }
433
434 fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
435 if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
437 if self.psess.edition.at_least_rust_2021() {
441 let lt = self.expect_lifetime();
442 let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
443 err.span_label(lo, "expected type");
444 return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
445 Ok(ref_ty) => ref_ty,
446 Err(err) => TyKind::Err(err.emit()),
447 });
448 }
449
450 self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
451 span: lo,
452 suggestion: lo.shrink_to_hi(),
453 });
454 }
455 Ok(TyKind::TraitObject(
456 self.parse_generic_bounds_common(allow_plus)?,
457 TraitObjectSyntax::None,
458 ))
459 }
460
461 fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
462 &mut self,
463 lt: Lifetime,
464 lo: Span,
465 mut err: Diag<'cx>,
466 ) -> Result<TyKind, Diag<'cx>> {
467 if !self.may_recover() {
468 return Err(err);
469 }
470 let snapshot = self.create_snapshot_for_diagnostic();
471 let mutbl = self.parse_mutability();
472 match self.parse_ty_no_plus() {
473 Ok(ty) => {
474 err.span_suggestion_verbose(
475 lo.shrink_to_lo(),
476 "you might have meant to write a reference type here",
477 "&",
478 Applicability::MaybeIncorrect,
479 );
480 err.emit();
481 Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))
482 }
483 Err(diag) => {
484 diag.cancel();
485 self.restore_snapshot(snapshot);
486 Err(err)
487 }
488 }
489 }
490
491 fn parse_remaining_bounds_path(
492 &mut self,
493 generic_params: ThinVec<GenericParam>,
494 path: ast::Path,
495 lo: Span,
496 parse_plus: bool,
497 ) -> PResult<'a, TyKind> {
498 let poly_trait_ref = PolyTraitRef::new(
499 generic_params,
500 path,
501 TraitBoundModifiers::NONE,
502 lo.to(self.prev_token.span),
503 );
504 let bounds = vec![GenericBound::Trait(poly_trait_ref)];
505 self.parse_remaining_bounds(bounds, parse_plus)
506 }
507
508 fn parse_remaining_bounds(
510 &mut self,
511 mut bounds: GenericBounds,
512 plus: bool,
513 ) -> PResult<'a, TyKind> {
514 if plus {
515 self.eat_plus(); bounds.append(&mut self.parse_generic_bounds()?);
517 }
518 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
519 }
520
521 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
523 let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
524 let span = self.prev_token.span;
525 self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {
526 span,
527 after_asterisk: span.shrink_to_hi(),
528 });
529 Mutability::Not
530 });
531 let ty = self.parse_ty_no_plus()?;
532 Ok(TyKind::Ptr(MutTy { ty, mutbl }))
533 }
534
535 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
538 let elt_ty = match self.parse_ty() {
539 Ok(ty) => ty,
540 Err(err)
541 if self.look_ahead(1, |t| *t == token::CloseBracket)
542 | self.look_ahead(1, |t| *t == token::Semi) =>
543 {
544 self.bump();
546 let guar = err.emit();
547 self.mk_ty(self.prev_token.span, TyKind::Err(guar))
548 }
549 Err(err) => return Err(err),
550 };
551
552 let ty = if self.eat(exp!(Semi)) {
553 let mut length = self.parse_expr_anon_const()?;
554 if let Err(e) = self.expect(exp!(CloseBracket)) {
555 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
557 self.expect(exp!(CloseBracket))?;
558 }
559 TyKind::Array(elt_ty, length)
560 } else {
561 self.expect(exp!(CloseBracket))?;
562 TyKind::Slice(elt_ty)
563 };
564
565 Ok(ty)
566 }
567
568 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
569 let and_span = self.prev_token.span;
570 let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
571 let (pinned, mut mutbl) = match self.parse_pin_and_mut() {
572 Some(pin_mut) => pin_mut,
573 None => (Pinnedness::Not, self.parse_mutability()),
574 };
575 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
576 if !self.look_ahead(1, |t| t.is_like_plus()) {
582 let lifetime_span = self.token.span;
583 let span = and_span.to(lifetime_span);
584
585 let (suggest_lifetime, snippet) =
586 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
587 (Some(span), lifetime_src)
588 } else {
589 (None, String::new())
590 };
591 self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
592
593 opt_lifetime = Some(self.expect_lifetime());
594 }
595 } else if self.token.is_keyword(kw::Dyn)
596 && mutbl == Mutability::Not
597 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
598 {
599 let span = and_span.to(self.look_ahead(1, |t| t.span));
601 self.dcx().emit_err(DynAfterMut { span });
602
603 mutbl = Mutability::Mut;
605 let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
606 self.bump();
607 self.bump_with((dyn_tok, dyn_tok_sp));
608 }
609 let ty = self.parse_ty_no_plus()?;
610 Ok(match pinned {
611 Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
612 Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
613 })
614 }
615
616 pub(crate) fn parse_pin_and_mut(&mut self) -> Option<(Pinnedness, Mutability)> {
620 if self.token.is_ident_named(sym::pin) {
621 let result = self.look_ahead(1, |token| {
622 if token.is_keyword(kw::Const) {
623 Some((Pinnedness::Pinned, Mutability::Not))
624 } else if token.is_keyword(kw::Mut) {
625 Some((Pinnedness::Pinned, Mutability::Mut))
626 } else {
627 None
628 }
629 });
630 if result.is_some() {
631 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
632 self.bump();
633 self.bump();
634 }
635 result
636 } else {
637 None
638 }
639 }
640
641 fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
644 self.expect(exp!(OpenParen))?;
645 let expr = self.parse_expr_anon_const()?;
646 self.expect(exp!(CloseParen))?;
647 Ok(TyKind::Typeof(expr))
648 }
649
650 fn parse_ty_bare_fn(
660 &mut self,
661 lo: Span,
662 mut params: ThinVec<GenericParam>,
663 param_insertion_point: Option<Span>,
664 recover_return_sign: RecoverReturnSign,
665 ) -> PResult<'a, TyKind> {
666 let inherited_vis = rustc_ast::Visibility {
667 span: rustc_span::DUMMY_SP,
668 kind: rustc_ast::VisibilityKind::Inherited,
669 tokens: None,
670 };
671 let span_start = self.token.span;
672 let ast::FnHeader { ext, safety, constness, coroutine_kind } =
673 self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?;
674 let fn_start_lo = self.prev_token.span.lo();
675 if self.may_recover() && self.token == TokenKind::Lt {
676 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
677 }
678 let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
679 let whole_span = lo.to(self.prev_token.span);
680
681 if let ast::Const::Yes(const_span) = constness {
690 let next_token_lo = if let Some(
691 ast::CoroutineKind::Async { span, .. }
692 | ast::CoroutineKind::Gen { span, .. }
693 | ast::CoroutineKind::AsyncGen { span, .. },
694 ) = coroutine_kind
695 {
696 span.lo()
697 } else if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety {
698 span.lo()
699 } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext {
700 span.lo()
701 } else {
702 fn_start_lo
703 };
704 let sugg_span = const_span.with_hi(next_token_lo);
705 self.dcx().emit_err(FnPointerCannotBeConst {
706 span: whole_span,
707 qualifier: const_span,
708 suggestion: sugg_span,
709 });
710 }
711 if let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind {
712 let next_token_lo = if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety
713 {
714 span.lo()
715 } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext {
716 span.lo()
717 } else {
718 fn_start_lo
719 };
720 let sugg_span = async_span.with_hi(next_token_lo);
721 self.dcx().emit_err(FnPointerCannotBeAsync {
722 span: whole_span,
723 qualifier: async_span,
724 suggestion: sugg_span,
725 });
726 }
727 let decl_span = span_start.to(self.prev_token.span);
729 Ok(TyKind::BareFn(P(BareFnTy { ext, safety, generic_params: params, decl, decl_span })))
730 }
731
732 fn recover_fn_ptr_with_generics(
734 &mut self,
735 lo: Span,
736 params: &mut ThinVec<GenericParam>,
737 param_insertion_point: Option<Span>,
738 ) -> PResult<'a, ()> {
739 let generics = self.parse_generics()?;
740 let arity = generics.params.len();
741
742 let mut lifetimes: ThinVec<_> = generics
743 .params
744 .into_iter()
745 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
746 .collect();
747
748 let sugg = if !lifetimes.is_empty() {
749 let snippet =
750 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
751
752 let (left, snippet) = if let Some(span) = param_insertion_point {
753 (span, if params.is_empty() { snippet } else { format!(", {snippet}") })
754 } else {
755 (lo.shrink_to_lo(), format!("for<{snippet}> "))
756 };
757
758 Some(FnPtrWithGenericsSugg {
759 left,
760 snippet,
761 right: generics.span,
762 arity,
763 for_param_list_exists: param_insertion_point.is_some(),
764 })
765 } else {
766 None
767 };
768
769 self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });
770 params.append(&mut lifetimes);
771 Ok(())
772 }
773
774 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
776 if self.token.is_lifetime() {
777 self.look_ahead(1, |t| {
778 if let token::Ident(sym, _) = t.kind {
779 self.dcx().emit_err(errors::MissingPlusBounds {
782 span: self.token.span,
783 hi: self.token.span.shrink_to_hi(),
784 sym,
785 });
786 }
787 })
788 }
789
790 let bounds = self.parse_generic_bounds()?;
792
793 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
794
795 Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
796 }
797
798 fn parse_precise_capturing_args(
799 &mut self,
800 ) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> {
801 let lo = self.token.span;
802 self.expect_lt()?;
803 let (args, _, _) = self.parse_seq_to_before_tokens(
804 &[exp!(Gt)],
805 &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
806 SeqSep::trailing_allowed(exp!(Comma)),
807 |self_| {
808 if self_.check_keyword(exp!(SelfUpper)) {
809 self_.bump();
810 Ok(PreciseCapturingArg::Arg(
811 ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
812 DUMMY_NODE_ID,
813 ))
814 } else if self_.check_ident() {
815 Ok(PreciseCapturingArg::Arg(
816 ast::Path::from_ident(self_.parse_ident()?),
817 DUMMY_NODE_ID,
818 ))
819 } else if self_.check_lifetime() {
820 Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
821 } else {
822 self_.unexpected_any()
823 }
824 },
825 )?;
826 self.expect_gt()?;
827 Ok((args, lo.to(self.prev_token.span)))
828 }
829
830 fn is_explicit_dyn_type(&mut self) -> bool {
832 self.check_keyword(exp!(Dyn))
833 && (self.token_uninterpolated_span().at_least_rust_2018()
834 || self.look_ahead(1, |t| {
835 (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::Star)
836 && !can_continue_type_after_non_fn_ident(t)
837 }))
838 }
839
840 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
844 let lo = self.token.span;
845 self.bump(); let syntax = if self.eat(exp!(Star)) {
849 self.psess.gated_spans.gate(sym::dyn_star, lo.to(self.prev_token.span));
850 TraitObjectSyntax::DynStar
851 } else {
852 TraitObjectSyntax::Dyn
853 };
854
855 let bounds = self.parse_generic_bounds()?;
857 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
858 Ok(TyKind::TraitObject(bounds, syntax))
859 }
860
861 fn parse_path_start_ty(
868 &mut self,
869 lo: Span,
870 allow_plus: AllowPlus,
871 ty_generics: Option<&Generics>,
872 ) -> PResult<'a, TyKind> {
873 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
875 if self.eat(exp!(Bang)) {
876 Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
878 } else if allow_plus == AllowPlus::Yes && self.check_plus() {
879 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
881 } else {
882 Ok(TyKind::Path(None, path))
884 }
885 }
886
887 pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
888 self.parse_generic_bounds_common(AllowPlus::Yes)
889 }
890
891 fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
895 let mut bounds = Vec::new();
896
897 while self.can_begin_bound()
903 || (self.may_recover()
904 && (self.token.can_begin_type()
905 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
906 {
907 if self.token.is_keyword(kw::Dyn) {
908 self.bump();
910 self.dcx().emit_err(InvalidDynKeyword {
911 span: self.prev_token.span,
912 suggestion: self.prev_token.span.until(self.token.span),
913 });
914 }
915 bounds.push(self.parse_generic_bound()?);
916 if allow_plus == AllowPlus::No || !self.eat_plus() {
917 break;
918 }
919 }
920
921 Ok(bounds)
922 }
923
924 fn can_begin_bound(&mut self) -> bool {
926 self.check_path()
927 || self.check_lifetime()
928 || self.check(exp!(Bang))
929 || self.check(exp!(Question))
930 || self.check(exp!(Tilde))
931 || self.check_keyword(exp!(For))
932 || self.check(exp!(OpenParen))
933 || self.check_keyword(exp!(Const))
934 || self.check_keyword(exp!(Async))
935 || self.check_keyword(exp!(Use))
936 }
937
938 fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
943 let lo = self.token.span;
944 let leading_token = self.prev_token;
945 let has_parens = self.eat(exp!(OpenParen));
946
947 let bound = if self.token.is_lifetime() {
948 self.parse_generic_lt_bound(lo, has_parens)?
949 } else if self.eat_keyword(exp!(Use)) {
950 let use_span = self.prev_token.span;
954 let (args, args_span) = self.parse_precise_capturing_args()?;
955 GenericBound::Use(args, use_span.to(args_span))
956 } else {
957 self.parse_generic_ty_bound(lo, has_parens, &leading_token)?
958 };
959
960 Ok(bound)
961 }
962
963 fn parse_generic_lt_bound(&mut self, lo: Span, has_parens: bool) -> PResult<'a, GenericBound> {
968 let lt = self.expect_lifetime();
969 let bound = GenericBound::Outlives(lt);
970 if has_parens {
971 self.recover_paren_lifetime(lo)?;
974 }
975 Ok(bound)
976 }
977
978 fn error_lt_bound_with_modifiers(
980 &self,
981 modifiers: TraitBoundModifiers,
982 binder_span: Option<Span>,
983 ) -> ErrorGuaranteed {
984 let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;
985
986 match constness {
987 BoundConstness::Never => {}
988 BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
989 return self
990 .dcx()
991 .emit_err(errors::ModifierLifetime { span, modifier: constness.as_str() });
992 }
993 }
994
995 match polarity {
996 BoundPolarity::Positive => {}
997 BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
998 return self
999 .dcx()
1000 .emit_err(errors::ModifierLifetime { span, modifier: polarity.as_str() });
1001 }
1002 }
1003
1004 match asyncness {
1005 BoundAsyncness::Normal => {}
1006 BoundAsyncness::Async(span) => {
1007 return self
1008 .dcx()
1009 .emit_err(errors::ModifierLifetime { span, modifier: asyncness.as_str() });
1010 }
1011 }
1012
1013 if let Some(span) = binder_span {
1014 return self.dcx().emit_err(errors::ModifierLifetime { span, modifier: "for<...>" });
1015 }
1016
1017 unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
1018 }
1019
1020 fn recover_paren_lifetime(&mut self, lo: Span) -> PResult<'a, ()> {
1022 self.expect(exp!(CloseParen))?;
1023 let span = lo.to(self.prev_token.span);
1024 let sugg = errors::RemoveParens { lo, hi: self.prev_token.span };
1025
1026 self.dcx().emit_err(errors::ParenthesizedLifetime { span, sugg });
1027 Ok(())
1028 }
1029
1030 fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
1042 let modifier_lo = self.token.span;
1043 let constness = if self.eat(exp!(Tilde)) {
1044 let tilde = self.prev_token.span;
1045 self.expect_keyword(exp!(Const))?;
1046 let span = tilde.to(self.prev_token.span);
1047 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1048 BoundConstness::Maybe(span)
1049 } else if self.eat_keyword(exp!(Const)) {
1050 self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
1051 BoundConstness::Always(self.prev_token.span)
1052 } else {
1053 BoundConstness::Never
1054 };
1055
1056 let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
1057 && self.eat_keyword(exp!(Async))
1058 {
1059 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1060 BoundAsyncness::Async(self.prev_token.span)
1061 } else if self.may_recover()
1062 && self.token_uninterpolated_span().is_rust_2015()
1063 && self.is_kw_followed_by_ident(kw::Async)
1064 {
1065 self.bump(); self.dcx().emit_err(errors::AsyncBoundModifierIn2015 {
1067 span: self.prev_token.span,
1068 help: HelpUseLatestEdition::new(),
1069 });
1070 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1071 BoundAsyncness::Async(self.prev_token.span)
1072 } else {
1073 BoundAsyncness::Normal
1074 };
1075 let modifier_hi = self.prev_token.span;
1076
1077 let polarity = if self.eat(exp!(Question)) {
1078 BoundPolarity::Maybe(self.prev_token.span)
1079 } else if self.eat(exp!(Bang)) {
1080 self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
1081 BoundPolarity::Negative(self.prev_token.span)
1082 } else {
1083 BoundPolarity::Positive
1084 };
1085
1086 match polarity {
1088 BoundPolarity::Positive => {
1089 }
1091 BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
1092 match (asyncness, constness) {
1093 (BoundAsyncness::Normal, BoundConstness::Never) => {
1094 }
1096 (_, _) => {
1097 let constness = constness.as_str();
1098 let asyncness = asyncness.as_str();
1099 let glue =
1100 if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
1101 let modifiers_concatenated = format!("{constness}{glue}{asyncness}");
1102 self.dcx().emit_err(errors::PolarityAndModifiers {
1103 polarity_span,
1104 polarity: polarity.as_str(),
1105 modifiers_span: modifier_lo.to(modifier_hi),
1106 modifiers_concatenated,
1107 });
1108 }
1109 }
1110 }
1111 }
1112
1113 Ok(TraitBoundModifiers { constness, asyncness, polarity })
1114 }
1115
1116 fn parse_generic_ty_bound(
1124 &mut self,
1125 lo: Span,
1126 has_parens: bool,
1127 leading_token: &Token,
1128 ) -> PResult<'a, GenericBound> {
1129 let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?;
1130
1131 let modifiers_lo = self.token.span;
1132 let modifiers = self.parse_trait_bound_modifiers()?;
1133 let modifiers_span = modifiers_lo.to(self.prev_token.span);
1134
1135 if let Some(binder_span) = binder_span {
1136 match modifiers.polarity {
1137 BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
1138 self.dcx().emit_err(errors::BinderAndPolarity {
1139 binder_span,
1140 polarity_span,
1141 polarity: modifiers.polarity.as_str(),
1142 });
1143 }
1144 BoundPolarity::Positive => {}
1145 }
1146 }
1147
1148 if self.token.is_lifetime() {
1151 let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
1152 return self.parse_generic_lt_bound(lo, has_parens);
1153 }
1154
1155 if let (more_lifetime_defs, Some(binder_span)) = self.parse_late_bound_lifetime_defs()? {
1156 lifetime_defs.extend(more_lifetime_defs);
1157 self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span });
1158 }
1159
1160 let mut path = if self.token.is_keyword(kw::Fn)
1161 && self.look_ahead(1, |t| *t == TokenKind::OpenParen)
1162 && let Some(path) = self.recover_path_from_fn()
1163 {
1164 path
1165 } else if !self.token.is_path_start() && self.token.can_begin_type() {
1166 let ty = self.parse_ty_no_plus()?;
1167 let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");
1169
1170 let path = if self.may_recover() {
1175 let (span, message, sugg, path, applicability) = match &ty.kind {
1176 TyKind::Ptr(..) | TyKind::Ref(..)
1177 if let TyKind::Path(_, path) = &ty.peel_refs().kind =>
1178 {
1179 (
1180 ty.span.until(path.span),
1181 "consider removing the indirection",
1182 "",
1183 path,
1184 Applicability::MaybeIncorrect,
1185 )
1186 }
1187 TyKind::ImplTrait(_, bounds)
1188 if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
1189 {
1190 (
1191 ty.span.until(tr.span),
1192 "use the trait bounds directly",
1193 "",
1194 &tr.trait_ref.path,
1195 Applicability::MachineApplicable,
1196 )
1197 }
1198 _ => return Err(err),
1199 };
1200
1201 err.span_suggestion_verbose(span, message, sugg, applicability);
1202
1203 path.clone()
1204 } else {
1205 return Err(err);
1206 };
1207
1208 err.emit();
1209
1210 path
1211 } else {
1212 self.parse_path(PathStyle::Type)?
1213 };
1214
1215 if self.may_recover() && self.token == TokenKind::OpenParen {
1216 self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?;
1217 }
1218
1219 if has_parens {
1220 if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
1223 let bounds = vec![];
1224 self.parse_remaining_bounds(bounds, true)?;
1225 self.expect(exp!(CloseParen))?;
1226 self.dcx().emit_err(errors::IncorrectParensTraitBounds {
1227 span: vec![lo, self.prev_token.span],
1228 sugg: errors::IncorrectParensTraitBoundsSugg {
1229 wrong_span: leading_token.span.shrink_to_hi().to(lo),
1230 new_span: leading_token.span.shrink_to_lo(),
1231 },
1232 });
1233 } else {
1234 self.expect(exp!(CloseParen))?;
1235 }
1236 }
1237
1238 let poly_trait =
1239 PolyTraitRef::new(lifetime_defs, path, modifiers, lo.to(self.prev_token.span));
1240 Ok(GenericBound::Trait(poly_trait))
1241 }
1242
1243 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1245 let fn_token_span = self.token.span;
1246 self.bump();
1247 let args_lo = self.token.span;
1248 let snapshot = self.create_snapshot_for_diagnostic();
1249 match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1250 Ok(decl) => {
1251 self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1252 Some(ast::Path {
1253 span: fn_token_span.to(self.prev_token.span),
1254 segments: thin_vec![ast::PathSegment {
1255 ident: Ident::new(sym::Fn, fn_token_span),
1256 id: DUMMY_NODE_ID,
1257 args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
1258 span: args_lo.to(self.prev_token.span),
1259 inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
1260 inputs_span: args_lo.until(decl.output.span()),
1261 output: decl.output.clone(),
1262 }))),
1263 }],
1264 tokens: None,
1265 })
1266 }
1267 Err(diag) => {
1268 diag.cancel();
1269 self.restore_snapshot(snapshot);
1270 None
1271 }
1272 }
1273 }
1274
1275 pub(super) fn parse_late_bound_lifetime_defs(
1277 &mut self,
1278 ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
1279 if self.eat_keyword(exp!(For)) {
1280 let lo = self.token.span;
1281 self.expect_lt()?;
1282 let params = self.parse_generic_params()?;
1283 self.expect_gt()?;
1284 Ok((params, Some(lo.to(self.prev_token.span))))
1287 } else {
1288 Ok((ThinVec::new(), None))
1289 }
1290 }
1291
1292 fn recover_fn_trait_with_lifetime_params(
1296 &mut self,
1297 fn_path: &mut ast::Path,
1298 lifetime_defs: &mut ThinVec<GenericParam>,
1299 ) -> PResult<'a, ()> {
1300 let fn_path_segment = fn_path.segments.last_mut().unwrap();
1301 let generic_args = if let Some(p_args) = &fn_path_segment.args {
1302 p_args.clone().into_inner()
1303 } else {
1304 return Ok(());
1307 };
1308 let lifetimes =
1309 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1310 &generic_args
1311 {
1312 args.into_iter()
1313 .filter_map(|arg| {
1314 if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1315 && let ast::GenericArg::Lifetime(lifetime) = generic_arg
1316 {
1317 Some(lifetime)
1318 } else {
1319 None
1320 }
1321 })
1322 .collect()
1323 } else {
1324 Vec::new()
1325 };
1326 if lifetimes.is_empty() {
1328 return Ok(());
1329 }
1330
1331 let inputs_lo = self.token.span;
1333 let inputs: ThinVec<_> =
1334 self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
1335 let inputs_span = inputs_lo.to(self.prev_token.span);
1336 let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
1337 let args = ast::ParenthesizedArgs {
1338 span: fn_path_segment.span().to(self.prev_token.span),
1339 inputs,
1340 inputs_span,
1341 output,
1342 }
1343 .into();
1344 *fn_path_segment = ast::PathSegment {
1345 ident: fn_path_segment.ident,
1346 args: Some(args),
1347 id: ast::DUMMY_NODE_ID,
1348 };
1349
1350 let mut generic_params = lifetimes
1352 .iter()
1353 .map(|lt| GenericParam {
1354 id: lt.id,
1355 ident: lt.ident,
1356 attrs: ast::AttrVec::new(),
1357 bounds: Vec::new(),
1358 is_placeholder: false,
1359 kind: ast::GenericParamKind::Lifetime,
1360 colon_span: None,
1361 })
1362 .collect::<ThinVec<GenericParam>>();
1363 lifetime_defs.append(&mut generic_params);
1364
1365 let generic_args_span = generic_args.span();
1366 let snippet = format!(
1367 "for<{}> ",
1368 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1369 );
1370 let before_fn_path = fn_path.span.shrink_to_lo();
1371 self.dcx()
1372 .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
1373 .with_multipart_suggestion(
1374 "consider using a higher-ranked trait bound instead",
1375 vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1376 Applicability::MaybeIncorrect,
1377 )
1378 .emit();
1379 Ok(())
1380 }
1381
1382 pub(super) fn check_lifetime(&mut self) -> bool {
1383 self.expected_token_types.insert(TokenType::Lifetime);
1384 self.token.is_lifetime()
1385 }
1386
1387 pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1389 if let Some((ident, is_raw)) = self.token.lifetime() {
1390 if matches!(is_raw, IdentIsRaw::No)
1391 && ident.without_first_quote().is_reserved()
1392 && ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name)
1393 {
1394 self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
1395 }
1396
1397 self.bump();
1398 Lifetime { ident, id: ast::DUMMY_NODE_ID }
1399 } else {
1400 self.dcx().span_bug(self.token.span, "not a lifetime")
1401 }
1402 }
1403
1404 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
1405 P(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
1406 }
1407}